原文网址:JS--对象数组深拷贝的方法_IT利刃出鞘的博客-CSDN博客
本文用示例介绍JavaScript对象数组深拷贝的方法。
对于普通数组(数组元素为数字或者字符串),深拷贝很简单,拷贝之后两个数组指针指向的存储地址不同,从而完成深拷贝。
- ar test = [1,2,3];//原数组
- var testCopy = [].concat(test);//拷贝数组
- testCopy[0]=4;
- console.log(test);// [1,2,3]
- console.log(testCopy);//[4,2,3]
对于对象数组
- //形如
- var objArr=[{"name":''weifeng"},{"name":"boy"}]
如果还是利用上述的[].concat()方法拷贝数组,则获取的结果仍然是浅拷贝,改变一个数组的内容,另一个数组的内容会改变。例子:
- var test = [{"name":"demi"},{"name":"lily"}];//原数组
- var testCopy = [].concat(test);//拷贝数组
- testCopy[1].name="test";
- console.log(test);// [{"name":"demi"},{"name":"test"}]
- console.log(testCopy);//[{"name":"demi"},{"name":"test"}]
从例子上可以看出,这种对于对象数组的拷贝,由于数组内部属性值为引用对象,因此整个拷贝还是浅拷贝,拷贝之后数组各个值的指针还是指向相同的存储地址。
- ar test = [{"name":"demi"},{"name":"lily"}];//原数组
- var testCopy = [].concat(JSON.parse(JSON.stringify(test)));//转换成json再转换成对象实现深拷贝
- testCopy[1].name="test";
- console.log(test);// [{"name":"demi"},{"name":"lily"}]
- console.log(testCopy);//[{"name":"demi"},{"name":"test"}]
仅在原对象包含可序列化值类型且没有任何循环引用时才有效。不可序列化值类型的一个例子:Date 对象 - Date 对象在JSON.stringify时会被转化为 String,JSON.parse 只能将其解析为字符串而无法解析回其原始的 Date 对象。
可序列化的值类型(没问题的类型)有:Boolean,Number,String,对象,数组
不可序列化的值类型(有问题的类型)有(以下问题都发生在JSON.stringify时):
- const _ = require('lodash');
-
- let one_brand = [
- {name: 'A', count: 1, value: Infinity},
- {name: 'B', count: 2},
- ]
-
- // 深拷贝
- let two_brand = _.cloneDeep(one_brand);
-
- console.log("改变前:")
- console.log(one_brand)
- console.log(two_brand)
-
- two_brand[1].count = 0;
-
- console.log("改变后:")
- console.log(one_brand)
- console.log(two_brand)
结果
- 改变前:
- [ { name: 'A', count: 1, value: Infinity },
- { name: 'B', count: 2 } ]
- [ { name: 'A', count: 1, value: Infinity },
- { name: 'B', count: 2 } ]
- 改变后:
- [ { name: 'A', count: 1, value: Infinity },
- { name: 'B', count: 2 } ]
- [ { name: 'A', count: 1, value: Infinity },
- { name: 'B', count: 0 } ]