说在前面
这是一个系列的文章,有兴趣的朋友可以查看此系列其它文章(持续更新ing)。本人才疏学浅,若有纰漏还请及时指出,请多指教!
情境描述
面试官:你了解js的深拷贝和浅拷贝吗?
我:深拷贝是连同引用地址和值一起拷贝;浅拷贝是只拷贝引用地址,不拷贝值,共用内存。
面试官:那浅拷贝和深拷贝如何实现?
我:用Object.create()实现深拷贝,(此处过了20秒钟),。。。
面试官:还有吗?
我:uhhhh,。。。忘了。。
面试官:那好,下一个问题。。。
(真想找个地洞钻进去。。。)
上面情景是大多数面试者都经历的事情,可是不能每次都被问倒呀,或许面试结束网上一搜就有解释,可是看一遍怎么会记得住呢?不妨记下来吧。
正题
深拷贝:复制了引用地址和值,相当于复制了一份副本,值相同,地址不同,互不影响。
浅拷贝:仅仅是复制了引用地址,也就是说新变量和旧变量共用内存,彼此的修改会互相影响。
1、如何实现深拷贝?
(1)手动赋值
var obj1 = {a: 1, b: 2};
var obj2 = {a: obj1.a, b: obj1.b};
obj2.a = 0;
console.log(obj1.a); // 1
obj1.a = 3;
console.log(obj2.a); // 0
(2)JSON
用JSON.stringify将对象转为字符串,再用JSON.parse将字符串转为对象。
var obj1 = {a: 1, b: 2};
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2); // {a: 1, b: 2}
obj2.a = 3;
console.log(obj1.a); // 1,不受影响
ps:只有能被转为json格式的对象才能这样用。
(3)Object.create
var obj1 = {a: 1, b: 2};
var obj2 = Object.create(obj1);
obj2.a = 3; // 在obj2的原型*问属性
console.log(obj1.a); // 1,不受影响
(4)递归拷贝
还没实现,下次更新。。。。
2、如何实现浅拷贝?
(1)赋值操作符(=)
对于(Boolean、String、Number、Undefined、Null)这五种基本数据类型,它们的复赋值是值传递,而对于对象的赋值是对引用赋值,所以使用“=”赋值对象就是对对象的浅拷贝。
var obj = {
a: 1,
b: 2
}
var obj1 = obj;
obj1.a = 3;
console.log(obj.a); // 3,被改了
obj.b = 0;
console.log(obj1.b); // 0,也被改了
(2)对象的解构赋值
var obj1 = {a: 1, b: {c: 2}};
var obj2 = {...obj1};
obj2.b.c = 3;
console.log(obj1.b.c); // 3
obj1.b.c = 0;
console.log(obj2.b.c); // 0
(3)Object.assign()
此方法是ES6中定义的方法,用于将源对象的所有可枚举属性复制到目标对象中,返回值是目标对象。用法如下:
Object.assign(targetObj, sourceObj1, ...sourceObjn);
例子:
let sourceObj = { a: { b: 1}};
let targetObj = {c: 3};
Object.assign(targetObj, sourceObj);
sourceObj.a.b = 2;
console.log(targetObj.a.b); // 2, 源对象的修改影响到了目标对象
targetObj.a.b = 4;
console.log(sourceObj.a.b); // 4, 目标对象的修改影响到了源对象
但是我发现一个奇怪的现象,如下所示:
obj的属性a竟然没有被修改,说明对于第一层属性,Object.assign是深拷贝。
参考资料
JSON教程https://www.runoob.com/json/json-tutorial.html
ES6对象https://www.runoob.com/w3cnote/es6-object.html