数组、对象的深拷贝与浅拷贝


所谓的浅拷贝和深拷贝:浅拷贝是在在拷贝过程中,遍历时那部分为对象/数组类型指向原来的地址,而深拷贝,则是完全开辟新的内存地址。
浅拷贝和深拷贝都是只针对于像 Object,Array这样的复杂对象。
默认情况下基本数据类型(number,string,null,undefined,boolean)都是深拷贝。

基本数据类型

基本数据类型,直接用等号赋值,也都是深拷贝

let a = 1;
let b = a;
b = 2;
console.log(a,b);  //打印出:1,2

b的数值改变并不会影响a,所以基本数据类型赋值就是深拷贝;

引用类型

引用类型,直接用等号赋值,是浅拷贝;

//对象
let a = {
    name: 'yinol'
};
let b = a;
b.name = 'yinol111';
console.log(a);

打印结果:a的数据被b改变,拷贝的时候并没有给b创造独立的内存,只是把a指向数据的 指针 拷贝给了b。

//数组
let arr = [1, 2, 3, [4, 5], {a: 6, b: 7}];
let arr2 = arr;
arr2[1] = 999;
console.log(arr); //[1, 999, 3, [4, 5], {a: 6, b: 7}]

ES6 解构赋值

//对象
const a = {
      name: 'name',
      age: 18,
      marriage: false,
    }

let { name, age, marriage} = a;

name = 'name1';
age = 20;
marriage = true;
console.log(a) 

打印结果:

a的数据并没有被改变,解构赋值好像是深拷贝啊?????看下一个例子

const a = {
      name: 'name',
      age: 18,
      marriage: false,
      addr: { province: 'yunnan', city: 'kunming' }
    }

let { name, age, marriage, addr } = a

name = 'myname'
age = 26
marriage = true
addr.province = 'shanghai'
addr.city = 'shanghai'

console.log(name, age, marriage, addr) 
console.log(a) 


解构赋值出来的对象将原对象a中的addr的数据修改了

let arr = [1, 2, 3, [4, 5], {a: 6, b: 7}];
let arr3 = [...arr];
arr[3][0]= -999;
console.log(arr);


总结:
解构赋值,如果所解构的原对象是一维数组或对象,其本质就是对基本数据类型进行等号赋值,那它就是深拷贝;
如果是多维数组或对象,其本质就是对引用类型数据进项等号赋值,那它就是浅拷贝;
解构赋值是浅拷贝(因为它确实不能对多维数组或对象达到深拷贝的作用)

深拷贝的方法

递归自定义函数实现深拷贝

要求对象中的属性值不能是函数、undefined以及symbol值

function deepCopy (obj) {
    // 创建一个新对象
    let result = {};
    temp = null;
    key = null;
    let keys = Object.keys(obj);
    keys.map((item, index) => {
        key = item;
        temp = obj[key];
        // 如果字段的值也是一个对象则递归操作
        if (temp && typeof temp === 'object') {
            result[key] = deepCopy(temp)
        } else {
            result[key] = temp
        }
    });
    return result
}
let obj1 = {
    x: {
        a: 1
    },
    y: undefined,
    z: function test (c, d) {
        return c+d
    },
    u: Symbol('test')
};
let obj2 = deepCopy(obj1);
obj2.x.a = 3;
console.log(obj1);
console.log(obj2);

利用lodash库的cloneDeep方法实现深拷贝

无法拷贝对象原型链上的属性和方法

var arr=[{a:1,b:2},{c:1,d:2}];
var arr2=_.cloneDeep(arr);
arr2[1].d=7;
console.log(arr,arr2);

JSON.parse(JSON.stringify(objectToClone)) 实现深拷贝

var arr=[{a:1,b:2},{c:1,d:2}];
var arr2=JSON.parse(JSON.stringify(arr));
    
arr2[1].d=7;
console.log(arr,arr2);

文章作者: yinol
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yinol !
  目录