交流群:462197261站长百科站长论坛热门标签收藏本站北冥有鱼 互联网前沿资源第一站 助力全行业互联网+
点击这里给我发消息
  • 当前位置:
  • 怎么使用javascript深度拷贝一个数组

    有两种数组拷贝类型:浅拷贝 & 深拷贝。浅拷贝只会拷贝数组的第一层,剩下的会引用。如果你需要一个嵌套的数组的拷贝,那需要你去深度拷贝这个数组。深拷贝,选择JSON方法或者Lodsh库吧

    const numbers = [1, [2], [3, [4]], 5];
    // Using JavaScript
    JSON.parse(JSON.stringify(numbers));
    // Using Lodash
    _.cloneDeep(objects);

    数组是引用类型

    为了搞清楚为什么有两种类型的拷贝,我们来深度了解一下基础知识然后解释什么是引用类型。
    与原始类型(number、string)不同,数组是引用类型。这意味着当你把一个数组赋值给一个变量,你是将数组的内存地址而非数组本身赋给变量。

    拷贝值类型

    这里没什么大不了的,我们创建一个value的拷贝。当我们改变valueCopy的值,它不会影响原来的value值。同理,当我们改变原来的值它也不会影响拷贝后的值。很好👍

    let value = 3;
    let valueCopy = value; // create copy
    console.log(valueCopy); // 3
    // Change valueCopy
    valueCopy = 100
    console.log(valueCopy); // 100
    // ✅ Original NOT affected 
    console.log(value); // 3

    拷贝引用类型

    好的,这里就会有点奇怪了!我们用同样的方法拷贝数组。

    let array = [1,2,3];
    let arrayCopy = array; // create copy
    console.log(arrayCopy); // [1,2,3];
    // Change 1st element of the array
    arrayCopy[0] = '👻';
    console.log(arrayCopy); // [ '👻', 2, 3 ]
    // ❌Original got affected
    console.log(array); // [ '👻', 2, 3 ]

    为什么原来的数组也受到了影响呢?好了,是因为:你拷贝的不是你拷贝的。说人话,意思就是你拷贝的只是指向数组内存空间的指针。引用类型不包含值,它们是指向内存中值的指针。

    拷贝引用类型的方法

    解决方法就是拷贝值而不是指针。

    let array = [1,2,3];
    let arrayCopy = [...array]; // create TRUE copy
    console.log(arrayCopy); // [1,2,3];
    // Change 1st element of the array
    arrayCopy[0] = '👻';
    console.log(arrayCopy); // [ '👻', 2, 3 ]
    // ✅ Original NOT affected 
    console.log(array); // [ 1, 2, 3 ]

    浅 & 深 拷贝

    当我使用展开扩展符号...来拷贝一个数组,我只是浅拷贝了一个数组。如果数组是嵌套或者多维的,这就不奏效了。

    let nestedArray = [1, [2], 3];
    let arrayCopy = [...nestedArray];
    // Make some changes
    arrayCopy[0] = '👻'; // change shallow element
    arrayCopy[1][0] = '💩'; // change nested element
    console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ]
    // ❌ Nested array got affected
    console.log(nestedArray); // [ 1, [ '💩' ], 3 ]

    如上,浅拷贝首层数组表现良好,然而,更改了嵌套数组元素,原始数组也受到影响💩。为了解决这个问题,就要用到深拷贝了。

    let nestedArray = [1, [2], 3];
    let arrayCopy = JSON.parse(JSON.stringify(nestedArray));
    // Make some changes
    arrayCopy[0] = '👻'; // change shallow element
    arrayCopy[1][0] = '💩'; // change nested element
    console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ]
    // ✅ Nested array NOT affected
    console.log(nestedArray); // 1, [ 2 ], 3 ]

    所以,这就完事了吗?要不要手写一个深拷贝引用类型的方法?

    const deepClone = obj => {
    const isObject = args => (typeof args === 'object' || typeof args === 'function') && typeof args !== null
    if (!isObject) throw new Error('Not Reference Types')
    let newObj = Array.isArray(obj) ? [...obj] : { ...obj }
    Reflect.ownKeys(newObj).map(key => {
    newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })
    return newObj
    }

    文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,

    您可能感兴趣的文章:

    • JavaScript中十种一步拷贝数组的方法实例详解
    • JS实现数组深拷贝的方法分析
    • js实现数组和对象的深浅拷贝
    • JavaScript数组深拷贝和浅拷贝的两种方法
    • javascript数组操作(创建、元素删除、数组的拷贝)

    广而告之:
    热门推荐:
    PC端微信扫码支付成功之后自动跳转php版代码

    本文实例为大家分享了php微信扫码支付成功之后自动跳转的具体代码,供大家参考,具体内容如下 场景: PC端   微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实···

    jQuery.prop() 使用详解

    prop()函数用于设置或返回当前jQuery对象所匹配的元素的属性值。 该函数属于jQuery对象(实例)。如果需要删除DOM元素的属性,请使用removeProp()函数。 语法 jQuery 1.6 新增该函数。prop()函数有以下两种用法: 用法一: jQueryObject.prop( propertyName [, value ] ) 设置或···

    javascript弹出带文字信息的提示框效果

    本文实例讲述了javascript弹出带文字信息的提示框效果。分享给大家供大家参考,具体如下: tooltips.js: // position of the tooltip relative to the mouse in pixel // var offsetx = 12; var offsety = 8; function newelement(newid) { if(document.createElement) { ···

    详解vue模拟加载更多功能(数据追加)

    使用vue制作加载更多功能,通过ajax获取的数据往data里面push经常不成功,原因是push是往数组中追加数据内容的,而不能用作数组之间的拼接,ajax获取的数据就是数组形式的,因此不成功,应该使用concat()拼接两个数组。 //这是错误的写法 $.ajax({ type:'get', async···

    php 变量引用与变量销毁机制详细介绍

    php 变量引用与变量销毁机制 在php中,符号”&”表示引用。 1、看看不引用的情况是这样子: $a = “hello world”;//定义一个变量,下面赋值给$b $b = $a;//这一步没有在$a之前加符号&,像这样子”$b= & $a”。没有加&,实际上原理是会将变量$a复制拷贝一份,也就是···

    jquery多浏览器捕捉回车事件代码

    复制代码 代码如下: $(document).keydown(function(event) { if (event.keyCode == 13) { $('form').each(function() { //你的要运行的代码 }); } }); 但是在opera中还是不行,技穷,一气之下把回车事件给屏蔽了 <form id="Form1" runat="server" onsubmit="return f···

    .net core webapi通过中间件获取请求和响应内容的方法

    本文主要根据中间件来实现对.net core webapi中产生的请求和响应数据进行获取并存入日志文件中; 这里不详细介绍日志文件的使用。你可以自己接入NLog,log4net,Exceptionless等 创建接口记录的中间件 using Microliu.Core.Loggers; using Microsoft.AspNetCore.Builder; using···

    浅谈类型转换操作符is/as

    1. 引言   类型安全是.NET设计之初重点考虑的内容之一,对于程序设计者来说,完全把握系统数据的类型安全,经常是力不从心的问题。现在,这一切已经在微软大牛们的设计框架中为你解决了。在.NET中,一切类型都必须集成自System.Object类型,因此我们可以很容易的获得对···

    Nodejs中读取中文文件编码问题、发送邮件和定时任务实例

    关于nodejs读取中文文件真是折腾了不少时间,网上各种方案,最后没有一个适用我,好在解决了。 下面的三个知识点都是从项目中抽出的,要单独运行脚本的话需要用全局模式来安装模块,比如安装中文转换模块(后续其它的也需要这么做): 复制代码 代码如下: npm install -g ico···

    常见的HTML标记错误写法

    我们最好开始注意了,因为HTML Police会走遍你的代码然后挑出你所有没有语义的标签,这份列表包含了10个最经常犯得HTML标签错误,记下他们,能够让我们避免犯此常见错误,让我们的HTML标签符合语义,和标准的要求. 罪行1:把块级元素放入了内联元素内 HTML 元素的表现方式不外乎就···