JavaScript自定义方法实现复杂对象的深拷贝

ES6中的Object.assign方法

     ES6中新增Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。


❗️注意点:

    Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。


实现

所以我们可以自己动手来手工实现复杂对象的深拷贝方法,具体实现有如下两种方法:

方法1⃣️

/**
 * 自定义方法实现复杂对象的深拷贝
 */
function deepCopy(obj) {
  let copy = {};

  // 如果是基本类型直接赋值,
  // 如果是数组则拷贝,
  // 其他对象则递归调用deepCopy方法
    Object.keys(obj).forEach(key => {

      if (obj[key] instanceof Array) {
        copy[key] = Array.from(obj[key]);
      }
      else if (typeof obj[key] === 'object') {
        copy[key] = deepCopy(obj[key]);
      }
      else {
        copy[key] = obj[key];
      }
    })

  return copy;
}

方法2⃣️

function deepCopy(obj) {
  return JSON.parse(JSON.stringify(obj));
}

验证

  以上通过两种方法实现了对象的深拷贝,下面通过数据进行简单验证:

//自定义一个复杂数据对象
let data = {
  name: 'Zhao',
  age: 22,
  url: 'https://microzz.com',
  scores:{
    math: 66,
    java: 88,
    test: [1, 2, 3]
  },
  skills: ['Node.js', 'ReactJS', 'ES6'],
  say() {
    console.log(`My name is ${this.name}`)
  }
}

//进行深拷贝,把数据保存在copyData
let copyData = deepCopy(data);

//对copyData进行修改,看是否对原数据有影响
copyData.name = 'Hui';
copyData.scores.math = 99;
copyData.scores.test[1] = 100;
copyData.skills[2] = 'ES5';
copyData.say = function () {
  console.log(`Copy: My name is ${this.name}`);
}

//打印输出查看结果进行验证
console.log(data);
/*
{ name: 'Zhao',
age: 22,
url: 'http://microzz.com',
scores: { math: 66, java: 88, test: [ 1, 2, 3 ] },
skills: [ 'Node.js', 'ReactJS', 'ES6' ],
say: [Function: say] }
 */

console.log(copyData);
/*
{ name: 'Hui',
age: 22,
url: 'http://microzz.com',
scores: { math: 99, java: 88, test: [ 1, 100, 3 ] },
skills: [ 'Node.js', 'ReactJS', 'ES5' ],
say: [Function] }
 */

data.say(); // My name is Zhao
copyData.say(); // Copy: My name is Hui

    两种方法的结果均一致,实现了对象的深拷贝,但是第二种方法通过原生的JSON.parse和JSON.stringify方法更为简单易懂。