JavaScript中深拷贝与浅拷贝

206 阅读2分钟

区分深拷贝与浅拷贝:

假设B复制了A,当修改A时,B随着A发生变化而变化,说明是浅拷贝,反之,如果B不随着A变化而变化,就是深拷贝。

浅拷贝例子:

let A = [2,2,3,4];
let B = A;
console.log(A === B); // true
A[0] = 1;
console.log("A: " + A); // A: [1,2,3,4]
console.log("B: " + B); // B: [1,2,3,4]

基本类型与引用类型

为了更好解释深拷贝与浅拷贝,下面简单地说明一下基本类型与引用类型

JavaScript基本数据类型有五种,Number、String、Boolean、Null、Undefined

JavaScript引用数据类型:Object、Array、Function等

基本类型的键和值都存储在栈内存中。如下图

因为变量a和变量b的处于的栈内存在不同位置,改变变量a的值时,变量b不会随着a改变而改变,这就是深拷贝

引用类型的键存储在栈内存中,值存储在堆内存中,但是栈内存会提供一个指向堆内存值的地址。

可以看出,A和B的堆地址都指向同一堆内存,当修改A的值时,B会受到影响,随着A的值改变而改变,这就是浅拷贝

实现深拷贝的三种方法

  • 利用递归循环复制层级属性

  •   function deepClone(obj) {
        let objClone = Array.isArray(obj) ? [] : {};
        if (obj && typeof obj === 'object') {
          for(key in obj){
            if(obj.hasOwnProperty(key)){
              // 判断obj子元素是否为对象,如果是,递归复制
              if(obj[key] && typeof obj[key] === 'object'){
                objClone[key] = deepClone[obj[key]];
              }else{
                objClone[key] = obj[key];
              }
            }
          }
          }
        return objClone;
      }
      let a = [2,2,3,4];
      let b = deepClone(a);
      a[0] = 1;
      console.log(b)
    
  • JSON对象的parse和stringify

  •   function deepClone1(obj){
        let _obj = JSON.stringify(obj);
        let objClone = JSON.parse(_obj);
        return objClone;
      }
      let a = [1,[1,2],3];
      let b = deepClone1(a);
      a[0] = 2;
      a[1][0] = 2;
      console.log(b);
    
  • JQ的extend方法

  •   /** * JQ的extend方法 
      * $.extend([deep],target,object1[,(objectN)]) 
      * deep为true则深拷贝,false就浅拷贝 
      * target为目标对象 * object为源对象 
      */
      let a = [1,[1,2],3];
      let b = $.extend(true,[],a);
      a[0] = 2;
      a[1][0] = 2;
      console.log(b);