【JavaScript】浅层拷贝与深层拷贝

【前言】
本系列为个人前端学习之路的学习笔记,在过往的学习过程中累积了很多笔记,如今想藉着IT邦帮忙这个平台做整理+再复习。
本系列标题一律以【】标示该篇文章主要涉及的内容,例如【JavaScript】、【Vue】等等。
若内容有误,还麻烦各路大神不吝於点出问题,感激不敬。


为何需要拷贝?

在JavaScript中,不同於纯值,物件是传参考

let obj1 = {
    num: 1
};
obj2 = obj1;
obj2.num = 2;
console.log(obj1.num); //2

在这个案例中,我们将obj赋值到obj2上,并且修改obj2属性的值
但因为物件传参考的特性,原本的obj1也会一起改到
为了避免这样的情况,我们希望把两个相同的物件分离(确实的复制一份,可以各自独立修改)
这时候就要使用拷贝,通常分为浅层拷贝和深层拷贝

浅层拷贝

浅层拷贝只有复制第一层,第二层内容仍是指向原本的参考
如果物件内属性的值是物件,那它的参考位置也会一同被复制过去,因此在这个案例中innerObj仍就是同一个物件

let obj1 = {
    num: 1,
    innerObj: {
        text: "inner"
    }
};
let obj2 = {};
for(let key in obj1){ 
	obj2[ key ] = obj1[ key ];
}
obj2.num = 2;
obj2.innerObj.text = "浅层拷贝无法保护到";
console.log(obj1.num); //1
console.log(obj1.innerObj.text); //浅层拷贝无法保护到

在这个案例中obj1的num属性在浅层拷贝时被拷贝到了obj2,因此修改obj2的num并不会让obj1的num产生影响
但因为innerObj是物件,因此拷贝过去的也是参考位置,obj1和obj2的innerObj还是同一个物件,因此还是会互相影响

浅层拷贝方法

这里列举几个浅层拷贝的方法,第一个就是上面用的:

let 新物件 = {}; //创造一个新的参考位置
//把旧物件的第一层属性复制过去
for(let key in 旧物件){ 
	新物件[ key ] = 旧物件[ key ];
}

此外,ES6也有新的写法,为let 新物件 = Object.assign( {} , 旧物件 )

let obj2 = Object.assign({},obj1);

或是使用展开:

let obj2 = {...obj1};

深层拷贝

深层拷贝会将新物件与旧物件完全彻底断开关系
即便有第三第四层的物件也不会出现问题

let obj1 = {
    num: 1,
    innerObj: {
        text: "inner"
    }
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.num = 2;
obj2.innerObj.text = "深层拷贝才保护得到";
console.log(obj1.num); //1
console.log(obj1.innerObj.text); //inner

深层拷贝会透过JSON.parseJSON.stringify将元物件转成字串再转回来,此时新物件与元物件就毫无关联


<<:  AWS Academy LMS 新增学生 - 教师

>>:  What's radiance?

{DAY 28} Matplotlib 绘图2

前言 这篇文章会延伸昨天所学 改变参数的使用 并且画出更多的图表 文章内容分别是 3. 折线图、散布...

[Day:27] GitHub Actions 懒人部署-ios CI 基础打包

在 Apple Actions 找到我们所需的 Actions apple-actions/imp...

MacOS读取蓝牙摇杆讯号,利用python修改pynput程序码实现 - 1.起始

1. 前言: 之前想要实现在几公尺外遥控 mac book,於是就在虾皮上找到了这个蓝牙摇杆,虽然怀...

Day 23 - 开发人员工具的日常

前言 今天再来聊聊另一个重要的工具,是很多人刚开始学 Javascript 就一路接触到现在,如果没...

[小故事]跌破众人眼镜! 聊聊 JavaScript 的封王之路

欢迎来到 Ian 的知识讲堂,本篇会用说故事的方式跟大家聊聊全端宠儿 - JavaScript 的小...