浅拷贝与深拷贝

浅拷贝与深拷贝

  浅拷贝和深拷贝是针对引用数据类型(对象、数组)而言的。以对象为例,下面一段代码是将对象obj1赋值给变量obj2

const obj1 = { a: 1, b: 2, c: 3, };
const obj2 = obj1;
console.log(obj2); // {a: 1, b: 2, c: 3}

值得注意的是,上面将对象obj1赋值给一个变量obj2时,并不是给该变量重新生成一个相同的对象,而是将该对象的索引指向该变量,也就是说obj1obj2指向同一个对象,它们本质上是同一个对象,可通过改变obj1obj2的值来证明。当改变obj2中的值时,相应的obj1对应的值也发生变化。

const obj1 = { a: 1, b: 2, c: 3, };
const obj2 = obj1;
obj2.a = 'change'
console.log(obj1); // {a: "change", b: 2, c: 3}
console.log(obj2); // {a: "change", b: 2, c: 3}

  上面将对象赋值的过程就是一个浅拷贝过程,浅拷贝它拷贝的是对象的索引,拷贝后的对象与原对象共享一个对象。其最大特点是修改拷贝后对象的值会影响到原对象的值。

  深拷贝则是完全的、彻彻底底的将对象复制一份,复制之后的对象与原对象相互独立,互不影响。其最大特点与浅拷贝相反,即修改拷贝后对象的值不会影响到原对象的值。

1、浅拷贝
1.1、Object.assign()

1.1.1、Object.assign()方法属于浅拷贝过程:

const obj3 = { a: 1, b: { b1: 2.1, b2: 2.2}, c: 3, };
const obj4 = Object.assign({}, obj3);
obj4.b.b1 = 'change';
console.log(obj3); // {a: 1, b: {b1: "change", b2: 2.2}, c: 3}
console.log(obj4); // {a: 1, b: {b1: "change", b2: 2.2}, c: 3}

可以看出当改变obj4b1的值时,obj3的也随之改变。

1.1.2、 需要注意的是Object.assign()可以实现对象结构深度为一层的深拷贝:

const obj5 = { a: 1, b: 2, c: 3, };
const obj6 = Object.assign({}, obj5);
obj6.b = 'change';
console.log(obj5); // {a: 1, b: 2, c: 3}
console.log(obj6); // {a: 1, b: "change", c: 3}

其中obj5对象结构的深度只有一层,obj6对象是由Object.assign()复制生成,在修改obj6b值之后,会发现obj5对象没有变化。

2、深拷贝

深拷贝的实现原理就是将对象中的每一个基本数据类型都复制一份到新建的对象中。

深拷贝的实现代码:

思路:对于要拷贝的数据,如果是基本数据类型,直接返回;如果是引用数据类型,则遍历数组或对象中的每一项并赋值给一个新建的数组或对象,如果被遍历的数组或对象元素为引用数据类型,则继续对该引用数据进行循环遍历,如此处理,直到将待拷贝数据中的每一个基本数据类型都复制到新建的对象中为止。

function deepClone(origin){
    // 判断需要深度克隆的对象是否是基本数据类型
    if(typeof origin === 'object'){
        // 判断深度克隆的对象是对象(狭义上的对象)还是数组
        let copy;
        if(origin instanceof Array){
            copy = [];
            for(let i in origin){
                copy.push(deepClone(origin[i])); // 通过递归实现深层克隆
            }
        }else{
            copy = {};
            for(let i in origin){
                copy[i] = deepClone(origin[i]); // 通过递归实现深层克隆
            }
        }
        return copy
    }else{
        return origin
    }
}

通过一些简单的例子验证:

测试例子1:

let x = 1;
let xCopy = deepClone(x);

这里写图片描述

对深拷贝后的对象进行修改:

xCopy = 2;

这里写图片描述

测试例子2:

let y = [1, 2, 3];
let yCopy = deepClone(y);

这里写图片描述

对深拷贝后的对象进行修改:

yCopy[0] = 'a';
yCopy[1] = 'b';

这里写图片描述

测试例子3:

let z = [1, 2, [3, 4]];
let zCopy = deepClone(z);

这里写图片描述

对深拷贝后的对象进行修改:

zCopy[0] = 'a';
zCopy[2] = 'b';

这里写图片描述

测试例子4:

let w = {a:1, b:2, c:[3, 4, 5]};
let wCopy = deepClone(w);

这里写图片描述

对深拷贝后的对象进行修改:

wCopy.a = 11;
wCopy.c = [33, 44, 55];

这里写图片描述

参考文献

[1] 关于JavaScript的浅拷贝和深拷贝
[2] 也来谈一谈js的浅复制和深复制
[3] js深拷贝和浅拷贝

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值