今天要讨论的主题是浅层複製及深层複製
又有人会称作 浅拷贝 以及 深拷贝
而深跟浅是怎么样定义的呢?我们就一样先来看例子说明吧!
var family = { name: '小明家', members: { father: '老爸', mom: '老妈', ming: '小明' }};
有的时候我们会希望用另一个变数,複製相同结构的物件,但我们又不希望他们指向的是同一个记忆体空间,除了之前提到的用 物件实字 的方式宣告之外,还有没有其他的办法呢?
这里提供两种办法,就是所谓的 浅拷贝 以及 深拷贝
浅层複製(浅拷贝)、Shallow Copy
浅拷贝指的就是没有办法每一层的物件都完全脱钩,包含三种方法,先以 for-in
的迴圈举例
1. for-in loop
var family = { name: '小明家', members: { father: '老爸', mom: '老妈', ming: '小明' }};var family2 = {};for(key in family) { console.log(key); // family 物件第一层有几个属性就跑几次 family2[key] = family[key];}console.log(family, family2);
这边的 key
不一定要叫做 key,你可以任意取名字,当 for-in 迴圈用在物件的时候,则会依照该物件的 第一层属性有几个就跑几次,以 family 的物件来说,第一层有 name 以及 members 两个属性,所以跑两次,而 key 就会是 属性的名称 ,所以跑第一次的时候 key 是 name
,第二次的时候 key 是 members
。
所以在依照这样的模式将值塞入 family2 之后,就完成 浅拷贝。
印出来以后可以看到两个物件的内容都长得一样
但是!!!!
如果我今天改动 family2.member.ming = '大明';
的时候,family.member.ming
也会跟着改动喔,因为他们两个物件中的子物件都还是 指向同一个记忆体位置的状态。
所以这就是浅拷贝的特点,虽然第一层是分开的,但第二层之后却还是有可能造成 call by reference(注1)的状况。
所以反之,深拷贝就是连物件中的子物件都会指向不同的记忆体空间,并且保持内容结构都一模一样。
2. jQuery extend
var family = { name: '小明家', members: { father: '老爸', mom: '老妈', ming: '小明' }};// jQuery extendvar family3 = jQuery.extend({}, family);console.log(family, family3);
3. ES6 Object.assign
var family = { name: '小明家', members: { father: '老爸', mom: '老妈', ming: '小明' }};// ES6 Object.assignvar family4 = Object.assign({}, family);console.log(family, family4);
深层複製(深拷贝)、Deep Copy
主要就是先把物件变成字串,再转回物件,这样他传参考的特性就会消失了喔!
var family = { name: '小明家', members: { father: '老爸', mom: '老妈', ming: '小明' }};var deepFamily = JSON.parse(JSON.stringify(family));console.log(family, deepFamily);
以上就是本篇文章的内容,希望对各位有帮助~汪汪
注1: 虽然上一篇文章提到 Javascript 是 call by sharing,但这里是用行为去描述,可以参考上一篇文章附的进阶文章内容。结论是依照不同行为的状况进行不同的分类(call by value/ reference / sharing)。