实现一个页面或者一个功能时,常常遇到的场景需要我们备份一个数组或者对象,这时候出现了深拷贝与浅拷贝效果截然不同呀总结如下:
- 浅拷贝:
var
arr = [1, 2, 3, 4],
shallowArr = arr;
arr[0] = "change";
console.log(arr);
console.log(shallowArr); //"change"
很简单的例子,很明显结果是两个数组第一项同时发生改变,原因是因为arr与shallowArr两数组为同一数组,仅仅是地址名不同,而地址却是同一个。那么如何避免上面的情况发生呢那就是深拷贝了。
- 深拷贝:
var
arr = [1, 2, 3, 4],
deepArr = [].concat(arr);
console.log(arr === shallowArr); // false
上述代码这是针对数组内部为简单类型的深拷贝,当数组内部的成员为引用类型时上面的方式还能算深拷贝吗?
var
arr = [{ m: 1 }, { n: 2 }],
deepArr = [].concat(arr);
console.log(arr === deepArr); // false
console.log(arr[0] === deepArr[0]); //true
很明显数组地址发生变化,但是数组内的对象地址并未变化,此时这种拷贝方式就是浅拷贝,所以说,不同场景下concat不是绝对滴~
那么问题来了,什么样的深拷贝才是绝对的捏~下面两种方式
- 序列化反序列化
var
arr = [{ m: 1 }, { n: 2 }],
deepArr = JSON.parse(JSON.stringify(arr));
console.log(arr === deepArr); // false
console.log(arr[0] === deepArr[0]); //false
序列化反序列化之后的对象一定是深拷贝,但是这种方式也有自己的弊端啦,我们看个栗子
new Date()
Wed Dec 26 2018 10:29:09 GMT+0800 (中国标准时间)
JSON.parse(JSON.stringify(new Date()))
"2018-12-26T02:28:42.932Z"
所以还是有坑的,使用的时候应该多注意。
- $.extend
var
arr = [],
deepArr = $.extend(true, [], arr);
arr === deepArr //false
- 自己DIY
function deepFunc(argc) {
var
newObj = {};
for (var property in argc) {
if (typeof argc[property] == "object") newObj[property] = deepFunc(argc[property]);
else newObj[property] = argc[property];
}
return newObj;
}
借用递归不停的赋值。
总结:
深拷贝对象都是js中引用类型的对象,基本类型的没有涉及,本质上就是引用类型的对象在堆上分配空间,而深拷贝就是重新给对象在堆上分配一个空间,然后将复制内容到这个新的空间中;而浅拷贝恰恰只是在栈上重新定义了一个指针,指向的位置却依然是原来引用对象的堆空间,改变指的时候当然就都变啦~
第一次在CSDN上发文章,有问题希望多给建议,蟹蟹~(排版不太好o(╯□╰)o)