怎么使用javascript深度拷贝一个数组

 更新时间:2019年06月06日 14:56:05   作者:Ioodu  
一般情况下,使用 “=” 可以实现赋值。但对于数组、对象、函数等这些引用类型的数据,这个符号就不好使了。下面我们来详细学习下吧

有两种数组拷贝类型:浅拷贝 & 深拷贝。浅拷贝只会拷贝数组的第一层,剩下的会引用。如果你需要一个嵌套的数组的拷贝,那需要你去深度拷贝这个数组。深拷贝,选择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中.?、??、??=的用法以及含义

    聊聊JavaScript中.?、??、??=的用法以及含义

    今天项目中突然遇到了不太明白的写法,下面这篇文章主要给大家介绍了关于JavaScript中.?、??、??=的用法以及含义的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • JavaScript实现简单轮播图效果

    JavaScript实现简单轮播图效果

    这篇文章主要为大家详细介绍了JavaScript实现图片轮播,左右翻转,图片切换显示等效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • 仅9张思维导图帮你轻松学习Javascript 就这么简单

    仅9张思维导图帮你轻松学习Javascript 就这么简单

    仅9张思维导图帮你轻松学习Javascript,从javascript变量、javascript运算符、javascript函数基础等多方面了解Javascript,就这么简单
    2016-06-06
  • 如何编写一个 Webpack Loader的实现

    如何编写一个 Webpack Loader的实现

    这篇文章主要介绍了如何编写一个 Webpack Loader的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • js+css实现计算器功能

    js+css实现计算器功能

    这篇文章主要为大家详细介绍了js+css实现计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • js实现数组的扁平化

    js实现数组的扁平化

    这篇文章主要为大家介绍了js实现数组扁平化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • Less 安装及基本用法

    Less 安装及基本用法

    这篇文章主要介绍了Less 安装及基本用法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • Javascript中构造函数要注意的一些坑

    Javascript中构造函数要注意的一些坑

    JavaScript语言是一门面向对象的语言,但JS中并没有类的概念的。于是JavaScript采用构造函数的方式来模拟类的效果,即我们通过函数来创建对象。这也证明了函数在JavaScript中具有非常重要的地位。本文主要介绍了Javascript中构造函数的一些坑,需要的朋友可以参考。
    2017-01-01
  • 用js判断输入是否为中文的函数

    用js判断输入是否为中文的函数

    本篇文章主要是对js判断输入是否为中文的函数进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-03-03
  • js实现单击可修改表格

    js实现单击可修改表格

    这篇文章主要为大家详细介绍了js实现单击可修改表格,类似成绩单,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04

最新评论