浅拷贝和深拷贝
2018-09-05 本文已影响12人
瓜田猹
一、ECMAScript数据类型
1)基本数据类型:简单的数据段(Number、String 、Boolean、Null和Undefined)
2)引用数据类型:多个值构成的对象(Object 、Array 、Function等)
二、变量的复制
1)原始值:将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已(且一个变量的改变不会影响另一个变量)。
2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是在栈内存多了一个指向这个对象指针罢了)
三、深复制和浅复制
浅拷贝: 浅拷贝就是流于表面的拷贝方式;当属性值为对象类型时,只拷贝了对象数据的引用(指针),导致新旧数据没有完全分离,还会互相影响。
深拷贝:深拷贝就是 ‘完全’拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会互相影响
四、如何实现对象、数组的深拷贝
1)方法一
JSON.parse(JSON.stringify(Obj))
注意:这种方式不能深拷贝有属性值为函数的对象
1)方法二
function deepCopy(target){
if(typeof target!=='object')return;
var newObj = target instanceof Array?[]:{};
for(var item in target){
//只复制元素自身属性,不复制原型链上的
if(target.hasOwnProperty(item)){
newObj[item] = typeof target[item]=='object'? deepCopy(target[item]):target[item]//是对象就把对象属性拆分出来赋值
}
}
return newObj;
}
var test = [1,'a',{name:'lei',age:18}];
var copy2 = deepCopy(test);
copy2[2].name = 'zhang';
console.log(test);// [1,'a',{name:'lei',age:18}];
console.log(copy2);// [1,'a',{name:'zhang',age:18}];
五、Object.assign()
用来复制一个对象
Object.assign({}, obj)
注意:Object.assign() 只是一级属性复制,比浅拷贝多深拷贝了一层而已
针对深拷贝,需要使用其他方法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
//可使用此方法拷贝(一级属性)
let obj1 = { a: 0 , b: 1};
let obj2 = Object.assign({}, obj1);
obj2.a = 1;
console.log(JSON.stringify(obj1)); // { a: 0, b:1}
console.log(JSON.stringify(obj2)); // { a: 1, b:1}
//不可使用此方法拷贝(多级属性)
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}//都改变了
参考:
https://www.cnblogs.com/cxying93/p/6106469.html
https://blog.csdn.net/u011277123/article/details/78376487