黑马程序员技术交流社区
标题: 【上海校区】javaScript记录浅拷贝与深拷贝 [打印本页]
作者: 梦缠绕的时候 时间: 2018-7-24 09:55
标题: 【上海校区】javaScript记录浅拷贝与深拷贝
在js中,一切皆对象(null和undefined有待另外的理解),JavaScript 中的几乎所有对象都是位于原型链顶部 Object 的实例。
对象的基本的一些操纵,我们是必须要知道的。
let obj = {
a: 1,
b: 2,
};
let copy = obj;
copy.a = 5;
console.log(obj.a); // ==> 5
上面的代码应该都能理解,赋值运算符不会创建一个对象的副本,它只分配一个引用,
那我们就想到了,循环遍历对象
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
shallowObj.a = 4 ==> obj.a =1
shallowObj.arr[1] = 5 ==> obj.arr[1] = 5
显然上面的遍历是起了一定的效果的,但是这只能算对象的浅拷贝(shallow copy),原因:因为浅拷贝只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅拷贝会导致 obj.arr 和 shallowObj.arr 指向同一块内存地址。
那改变一下上面的代码,我们需要用迭代来实现对对象的深拷贝(deep copy)
var obj = { a:1, arr: [2,3] };
var deepObj = deepCopy(obj);
function deepCopy(obj) {
var newObj = obj.constructor === Array ? [] : {}
if (typeof obj !== 'object') {
return
} else {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
// 判断子元素是否为对象
newObj = typeof obj === 'object' ? deepCopy(obj) : obj
}
}
}
return newObj
}
deepObj.arr[1] = 5
console.log(obj.arr[1]) ==> 3
解释:知乎网友的解释
对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,而深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
项目中,我也遇到Object.assign({},obj) 这种浅拷贝与JSON.parse(JSON.stringfy(obj))这种深拷贝,但是JSON.parse(JSON.stringfy(obj)) 这种方法是有缺陷的,其并不能复制,对象中的方法,但是Object.assign({},obj)可以。
let obj = {
name: 'demo',
test: function test() {
return true;
},
}
let method1 = Object.assign({}, obj);
let method2 = JSON.parse(JSON.stringify(obj));
console.log(method1);
/* result
{
test: function test() {
return true;
},
name: "demo"
}
*/
console.log(method2);
/* result
{
name: "demo"
}
*/
最后,我也看到了一篇文章,《深入剖析 JavaScript 的深复制》,涉及到 jQuery, underscore, lodash 等库关于深复制的实现,有兴趣可以看看。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |