js深拷贝

280 阅读2分钟

该文章主要用于自己在平时学习记录使用

浅拷贝与深拷贝

主要是针对js中引用类型的复制。在引用类型中,定义的变量相当于一个指针,指向了某个对象或数组的引用

浅拷贝

let obj = {a: 1, b: 1};
let newObj = obj;
newObj.a = 2;
console.log(obj.a);  // 2

newObjobj这两个变量都存储了指向对象的一个引用地址,实则共用一个对象,所以当改变newObj.a = 2时,obj.a也发生改变。这就是浅拷贝

深拷贝

深拷贝就是让newObj.a发送变化时,obj.a不发生变化,newObjobj相当于两个完全不同的对象。

深拷贝方法

  • 使用最原始的方法,建立一个新的空对象或数组,遍历每个元素,将其放到新的对象或数组中,如果碰到元素也是引用类型的,则进行递归。
  • 当进行深拷贝的元素数据为一个数组时,可以使用slice()或者concat()或者ES6中的扩展运算符(该方法也可用于一个对象)方法,但是该方法有个问题,当数组的元素也是一个引用类型时,则无法进行深层次的深拷贝。
    let arr = [1, 2, [3, 4], {a: 1, b: 2}];
    let newArr = arr.slice(); //newArr -> [1, 2, [3, 4], {a: 1, b: 2}]
    newArr[0] = 'change';
    console.log(arr, newArr);

可以发现:newArr通过slice()方法复制了arr,当改变newArr第一层的元素时,arr不受影响

当改变深层的元素内容时,再来看一下效果:

可以发现:newArrarr的元素值都有变化

经测试,concat()ES6拓展运算符slice()情况相同,有兴趣的童鞋可以自己试验下,童叟无欺!!!

  • 最暴力、最直接的方式:JSON.parse(JSON.stringify(obj)),但是该方法也有一些缺陷:

    1.数组

    数组元素有 undefinednull时:

    let arr = [undefined, 1, 2, 3, null];
    console.log(JSON.parse(JSON.stringify(arr)));  // [ null, 1, 2, 3, null ];
    

    其中undefined被转为null, null依然为null

    2.对象

    对象中有属性的valueundefined 或者 null时:

    let obj = {a: 1, b: undefined, c: null, d: 'null', e: 'undefined'};
    console.log(JSON.parse(JSON.stringify(obj))); // { a: 1, c: null, d: 'null', e: 'undefined' }
    

    其中valueundefined的属性被剔除,其余情况不变。