前一篇结尾讲到了物件的传参考的特性,但有时候我们希望属性和值是被直接複製一份,并非是直接指向的
浅複製(shallow copy)
如果用一般比较传统的方式,会使用 for in 的作法:
var person = { name: 'Jerry', members: { father: 'John', mother: 'Mary' }};var person2 = {};for(var key in person){ person2[key] = person[key]}
这时候如果在 person2 更改 name 属性,person 是不会被影响的,这是因为当命名 person2 为空物件的时候,已经把它指向另外一个记忆体空间,接着把 person 的属性用 for 迴圈一一的传递给 person2,就可以把一个物件複製
当然 ES6 提供了一个不错的方法可以做使用 Object.assign()
,方法内是一个空物件跟要被複製的物件变数:
var person2 = Object.assign({}, person);
这个方法结果会跟上面是一样的,只是更为简洁好用
上面所讲的都是浅複製,为什么是浅複製呢 ?
因为当我们尝试去更改 person2 的 members 物件属性的内部属性时,person 的 members 属性也被做更动了,这是因为 members 这个物件属性,它也是一个物件,所以也是独立的记忆体空间,即使複製了,指向的位置依然没有变动
所以为了这种多层次的物件,有另外一种複製的方式
深複製(deep copy)
听起来虽然很深奥,但其实只是运用了 JavaScript 的转字串跟转物件的方式而已
// 首先先把物件格式转成字串JSON.stringify(person);// 再转回去物件,并赋予一个变数var person3 = JSON.parse(JSON.stringify(person));
转完之后,先来更改一下 person3 的物件属性 members 的 mother 属性person3.members.mother = 'Anna';
再用 console 分别查看 person 和 person3 的物件属性 members 的 mother 属性
console.log(person.members.mother, person3.members.mother);// Mary, Anna
就会发现资料已经不会互相影响了,进一步一样可以用 ===
来检查
console.log(person.members === person3.members);// false
这样彼此的 members 物件属性就分别指向不同的记忆体空间,也完成了物件属性的複製
这就是深複製(deep copy)