js深拷贝与浅拷贝
实现一个页面或者一个功能时,常常遇到的场景需要我们备份一个数组或者对象,这时候出现了深拷贝与浅拷贝效果截然不同呀总结如下:
浅拷贝:
1 var 2 arr = [1, 2, 3, 4], 3 shallowArr = a; 4 arr[0] = "change"; 5 console.log(arr); 6 console.log(shallowArr);
很简单的例子,很明显结果是两个数组第一项同时发生改变,原因是因为arr与shallowArr两数组为同一数组,仅仅是地址名不同,而地址却是同一个。那么如何避免上面的情况发生呢那就是深拷贝了。
深拷贝:
1 var 2 arr = [1, 2, 3, 4], 3 deepArr = [].concat(arr); 4 console.log(arr === shallowArr); // false
上述代码这是针对数组内部为简单类型的深拷贝,当数组内部的成员为引用类型时上面的方式还能算深拷贝吗?
1 var 2 arr = [{ m: 1 }, { n: 2 }], 3 deepArr = [].concat(arr); 4 console.log(arr === deepArr); // false
5 console.log(arr[0] === deepArr[0]); //true
很明显数组地址发生变化,但是数组内的对象地址并未变化,此时这种拷贝方式就是浅拷贝。
最实用的深拷贝实现方式:
1 var 2 arr = [{ m: 1 }, { n: 2 }], 3 deepArr = JSON.parse(JSON.stringify(arr)); 4 console.log(arr === deepArr); // false 5 console.log(arr[0] === deepArr[0]); //false
序列化然后反序列化重新生成一个新的数组(引用对象)。
对象的浅拷贝:
var obj_a = { name: "dqhan", age: 25, sex: "male", hobby: { 1: "eat", 2: "play" } }, obj_b = obj_a; obj_b.age = 18;
对象的深拷贝:
var obj_a = { name: "dqhan", age: 25, sex: "male", hobby: { 1: "eat", 2: "play" } } 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中引用类型的对象,基本类型的没有涉及,本质上就是引用类型的对象在堆上分配空间,而深拷贝就是重新给对象在堆上分配一个空间,然后将复制内容到这个新的空间中;而浅拷贝恰恰只是在栈上重新定义了一个指针,指向的位置却依然是原来引用对象的堆空间,改变指的时候当然就都变啦~