关于深拷贝和浅拷贝
从原理看:
- 浅拷贝:拷贝一层,对象级别的则拷贝引用
- 深拷贝:拷贝多层,每个层级的属性都会拷贝
从现象看:
A复制了B,B被修改后,
- A随B变化而变化->浅拷贝
- A不变->深拷贝
深拷贝针对的s复杂的object类型数据
∴如直接赋值的单层拷贝,如b=a,b虽然不受a的影响,但是这也不算做深拷贝
现象只是作为方便理解的一个参考,真正的判断标准还是要从原理上看
数据类型分为:
- 基本数据类型(7种):namevalue都存储在栈内存中
- 引用数据类型:name->栈内存,值->堆内存,栈内存会提供一个引用的地址指向堆内存的值
当b=a进行拷贝时,b复制的是a的引用地址,并不是堆里面的值,所以这便造成了当a发生改变,b也会随之改变的浅拷贝
实现浅拷贝的方法:
一、 直接复制
//基本数据类型
var arr = [1, 2, 3, '4'];
var arr2 = arr;
arr2[1] = "test";
console.log(arr); // [1, "test", 3, "4"]
console.log(arr2); // [1, "test", 3, "4"]
//改变其中一个对象的属性值,两个对象都发生了改变
//obj和obj2两个变量都指向同一个指针,赋值时只是复制了指针地址,它们指向同一个引用,∴当我们改变其中一个的值,另一个变量的值也会随之改变
----------
//对象级
function Clone(obj1){
var obj2 ={};
for(var i in obj1)
{
obj2[i]=obj1[i];
}
return obj2;
}
浅拷贝只是拷贝了一层,除了对象是拷贝引用类型,其他的都是直接将值传递,有自己的内存空间
二、ES6中的Object.assign()方法
该方法可以把任意多个的源对象自身的可枚举属性拷贝给对象,然后返回目标对象
Object.assign(目标对象,任意多个源对象)
var obj1 = {
a: "hello",
b: {
a: "hello",
b: 21}
};
var cloneObj1= Object.assign({}, obj1);
cloneObj1.a = "changed";
cloneObj1.b.a = "changed";
console.log(obj1.a); //hello
console.log(obj.b.a); // "changed"
如果对象只有一层,这个函数可以作为深拷贝的方法
var obj2 = { a: 10, b: 20, c: 30 };
var cloneObj2 = Object.assign({}, obj2);
cloneObj2.b = 100;
console.log(obj2);
// { a: 10, b: 20, c: 30 } <-- 没有改变,实现了深拷贝
console.log(cloneObj2);
// { a: 10, b: 100, c: 30 }
若想实现深拷贝,就需要在堆中开辟一个内存,用来存放b的值。
方法一、手动复制
将A对象项的属性逐个负责给另一个对象的属性
var ob1 = {a:1,b:2,c:3};
var ob2 = {a:ob1.a,b:ob1.b,c:ob1.c};
ob1.a = 0;
ob2.b = 0;
console.log(ob1);//023
console.log(ob2);//103
这样很麻烦,且本质上不能算作深拷贝,当ob1内嵌套对象c时,ob1和ob2将共享c,当改变c的属性时,ob1ob2将都发生改变
方法二、将对象通过JSON方法转成字符串再转回来
可以实现真正的深拷贝,但是只能用于可以转成JSON格式的对象,function无法转换成JSON,就不能够使用
∴此方法会舍弃对象的构造函数
var ob1 ={c:{a:1,b:2}};
var ob2 =JSON.parse(JSON.stringfy(ob1));
//用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
方法三、递归拷贝
function deepClone(obj1,obj2){
var obj = obj2|| {};//如果obj存在则定义为obj2,否则建立空对象
for(var i in obj1){//遍历原对象
if(typeof obj1[i] === 'object'){//如果当前元素是对象
obj[i] = Array.isArray(obj1[i]) ?[]:{};//判断是数组还是对象
deepClone(obj1[i],obj[i]);//利用递归逐层遍历直到最后一层
}
else{
obj[i] = obj1[i];//赋值
}
}
return obj;
}
var str = {};
var obj = { a: {a: "Leemo", b: 19980228} };
deepClone(obj, str);
console.log(str.a);
方法四、使用Object.create()方法
var Obj2 = object.create(Obj1);
//实现Obj2深拷贝Obj1
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。