Object.assign 是深拷贝?是浅拷贝?都不是!

前言

前天,一次面试,一个挺专业的面试官问我,如何用原生js方法简单实现深拷贝?

我一脸问号,有么?然后面试官暗示了我半天,我说,莫非你是指Object.assign?

我就有点流汗,从没听说Object.assign跟深拷贝有什么关系,我又孤陋寡闻了?

测试

赶紧查了查资料,经过测试得知,Object.assign 既不是深拷贝,也不是浅拷贝。测试代码如下:

let a = {name: {asd: '123'}};
let b = Object.assign({}, a);
a = {w: []};
console.log(a); // w: []

let m = {name: {asd: '123'}};
let n = Object.assign({}, m);
m.name = [];
console.log(n); // name: {asd: "123"}

let x = {name: {asd: '123'}};
let y = Object.assign({}, x);
x.name.asd = 456;
console.log(y); // name: {asd: 456}

let p = {name: {asd: {xyz: '123'}}};
let q = Object.assign({}, p);
p.name.asd.xyz = 456;
console.log(p); // name: asd: {xyz: 456}

结论

所以结论是:

Object.assign的拷贝,对于第一层属性是深拷贝,对于深层属性是浅拷贝。

所以Object.assign的深拷贝的用法是:

  1. 只一层属性的前提下,就是深拷贝。

  2. 多层属性的前提下,如果你保证你和其他人绝对不会修改原对象的深层属性,那么可以使用Object.assign实现“所谓的”深拷贝,如果你无法保证,就不要把Object.assign的拷贝当做深拷贝来用。

为什么会有这个现象?

因为属性的值也是对象的时候,也是对这个对象的引用,Object.assign将对象的引用复制过来,其实没毛病。

先用Object.freeze冻结原对象行不行?

那就要了解一下Object.freeze冻结原理,测试过程我就不说了,结论是:

Object.freeze也是只能冻结第一层属性。

所以不要有“用Object.freeze先冻结再深拷贝”的念头!

怎样才是严谨的深拷贝?

严谨是一个相对概念,深拷贝的写法也有N种,我个人是采用2种办法,一个是去github上找一个深拷贝的开源代码,或者是使用lodash的深拷贝就得了。

你可能感兴趣的:(Object.assign 是深拷贝?是浅拷贝?都不是!)