怎么使用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
}

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

(0)

相关推荐

  • JavaScript中十种一步拷贝数组的方法实例详解

    JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下. 1.扩展运算符(浅拷贝) 自从ES6出现以来,这已经成为最流行的方法.它是一个很简单的语法,但是当你在使用类似于React和Redux这类库时,你会发现它是非常非常有用的. numbers = [1, 2, 3]; numbersCopy = [...numbers]; 这个方法不能有效的拷贝多维数组.数组/对象值的拷贝是通过引用而不是值复制. // numbersCopy.push(4);

  • javascript数组操作(创建、元素删除、数组的拷贝)

    1.数组的创建 复制代码 代码如下: var arrayObj = new Array(); //创建一个数组var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度var arrayObj = new Array([element0[, element1[, ...[, elementN]]]]); 创建一个数组并赋值 要说明的是,虽然第二种方法创建数组指定了长度,但实际上所有情况下数组都是变长的,也就是说即使指定了长度为5,仍然可以

  • JavaScript数组深拷贝和浅拷贝的两种方法

    例如这个例子: 复制代码 代码如下: var arr = ["One","Two","Three"]; var arrto = arr;arrto[1] = "test";document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,test,Threedocument.writeln("数组的新值

  • js实现数组和对象的深浅拷贝

    前提:原始数据类型和对象类型赋值时的差异 JavaScript的数据类型分为原始数据类型和对象类型.二者在内存中存放的方式不同,导致了其赋值时差异.分别举个栗子 var x = 1; var y = x; //y获得了和x同样的值 y = 2; console.log(x); // 1 var m = [1,2]; //m存放的是指向[1,2]这个数组对象的引用地址 var n = m; //n也获得 [1,2]数组对象的引用地址 n[0] = 3; console.log(m); //[3,2

  • JS实现数组深拷贝的方法分析

    本文实例讲述了JS实现数组深拷贝的方法.分享给大家供大家参考,具体如下: 最近在网上看到一篇关于js数组复制最有效的方法是直接使用slice和concat方法.这2个方法的确是最快的把数组成功复制,而不是引用.可以运行实例: <script type="text/javascript"> <!-- var arr1=["1","2","3"],arr2; arr2=arr1.slice(0); arr1[0]

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

    有两种数组拷贝类型:浅拷贝 & 深拷贝.浅拷贝只会拷贝数组的第一层,剩下的会引用.如果你需要一个嵌套的数组的拷贝,那需要你去深度拷贝这个数组.深拷贝,选择JSON方法或者Lodsh库吧 const numbers = [1, [2], [3, [4]], 5]; // Using JavaScript JSON.parse(JSON.stringify(numbers)); // Using Lodash _.cloneDeep(objects); 数组是引用类型 为了搞清楚为什么有两种类型的拷

  • Javascript中克隆一个数组的实现代码

    08年一家公司JS面试题,职位是javascript工程师(赴google) 面试官问我如何克隆一个数组,当时想了下js的Object没有clone方法,java的Object有. 那怎么得到一个新数组呢? 我当时回答:用一个loop将源数组元素依次push到新数组中.这是最简单的方法,但显然不是面试官想要的答案. 最后告知我:利用Array的slice方法.示例如下: 复制代码 代码如下: var ary = [1,2,3];//源数组 var ary2 = ary.slice(0);//克隆

  • JavaScript中有关一个数组中最大值和最小值及它们的下表的输出的解决办法

    今天在学习js中的数组时,遇到的输出一个数组中最大.最小值以及它们的下表,以下是自己的解决方法! <script type="text/javascript"> var arr = [14, 14, 53, 14, 14, 53, 67, 67]; var max = arr[0],min = arr[0]; var maxIndex = []; maxIndex[0] = 0; var minIndex = []; minIndex[0] = 0; var j = 1,

  • JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例

    本文实例讲述了JavaScript求一个数组中重复出现次数最多的元素及其下标位置.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>数组重复次数</title> </head> <body> <script language="Jav

  • js中如何复制一个数组(浅复制、深复制)

    目录 下面介绍数组的浅复制 方法一:concat() 方法二:slice() 方法三:扩展运算符 方法四: Object.assign() 下面是深复制 方法一:JSON.parse(JSON.stringify(arr)) 方法二:通用方法(数组或对象) 方法三:利用lodash的深拷贝函数 在Vue中使用 安装 在main.js中引入 使用 总结 在js中,我们经常会用到数组复制,Array是引用类型,如果用arrA=arrB简单的把一个数组赋值,并没有创造出一个新数组,arrA和arrB其

  • JavaScript将一个数组插入到另一个数组的方法

    本文实例讲述了JavaScript将一个数组插入到另一个数组的方法.分享给大家供大家参考.具体分析如下: 这段JS代码可以通过Array.prototype.push.apply方法将一个数组插入到另外一个数组,下面的代码将数组b插入到a var a = [4,5,6]; var b = [7,8,9]; Array.prototype.push.apply(a, b); uneval(a); // is: [4, 5, 6, 7, 8, 9] 希望本文所述对大家的javascript程序设计有

  • 如何用JavaScript实现一个数组惰性求值库

    概述 在编程语言理论中,惰性求值(英语:Lazy Evaluation),又译为惰性计算.懒惰求值,也称为传需求调用(call-by-need),是一个计算机编程中的一个概念,它的目的是要最小化计算机要做的工作.它有两个相关而又有区别的含意,可以表示为"延迟求值"和"最小化求值",除可以得到性能的提升外,惰性计算的最重要的好处是它可以构造一个无限的数据类型. 看到函数式语言里面的惰性求值,想自己用JavaScript写一个最简实现,加深对惰性求值了解.用了两种方法,

  • javascript中判断一个值是否在数组中并没有直接使用

    在JS中要判断一个值是否在数组中并没有函数直接使用,如PHP中就有in_array()这个函数.但我们可以写一个类似in_array()函数来判断是一个值否在函数中 例1 复制代码 代码如下: /* * * 判断在数组中是否含有给定的一个变量值 * 参数: * needle:需要查询的值 * haystack:被查询的数组 * 在haystack中查询needle是否存在,如果找到返回true,否则返回false. * 此函数只能对字符和数字有效 * */ function findnum(){

  • JavaScript jQuery 中定义数组与操作及jquery数组操作

    首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象 Javascript不支持多维数组,但是因为数组里面可以包含对象(数组也是一个对象),所以数组可以通过相互嵌套实现类似多维数组的功能 1.1 定义数组 声明有10个元素的数组 复制代码 代码如下: var a = new Array(10); 此时为a已经开辟了内存空间,包含10个元素,用数组名称加 [下标] 来调用,例如

  • JavaScript深度复制(deep clone)的实现方法

    在代码复用模式里面有一种叫做"复制属性模式"(copying properties pattern).谈到代码复用的时候,很有可能想到的是代码的继承性(inheritance),但重要的是要记住其最终目标--我们要复用代码.继承性只是实现代码复用的一种手段,而不是唯一的方法.复制属性也是一种复用模式,它跟继承性是有所不同的.这种模式中,对象将从另外一个在对象中获取成员,其方法是仅需将其复制即可.用过jQuery的都知道,它有一个$.extend()方法,它的用途除了扩展第三方插件之外,

随机推荐