如何实现一个对象的深拷贝(五种方法总结)

37 阅读2分钟

昨天面试闻远科技碰到一个很常见的问题,以后的面试题都记录一下吧

1、json暴力转化

通过JSON.stringify和JSON.parse()将对象转化成字符串之后在转化成对象。

let obj = { name: '张三', address: '中国台湾省'}
let obj2 = JSON.parse(JSON.stringify(obj))
consloe.log(obj) // address: '中国台湾省' name: '张三' 以对象格式打印
consloe.log(obj2) // address: '中国台湾省' name: '张三' 以对象格式打印

这种方式简单粗暴,但是存在弊端,当值为undefined、function、symbol会在转换中被忽略。

2、ES6解构赋值

 let obj = { name: '123', age: 13 };
 let obj2 = { ...obj }
  console.log(obj); // { "name": "123", "age": 13}
  console.log(obj2); // { "name": "123", "age": 13}

只能深层拷贝第一层,如果对象中的属性也是对象,将无法进行深度copy

3、for in遍历对象进行copy

 let obj3 = { name: '李四', age: 20}
  let obj4 = {}
  for(var key in obj3){
    obj4[key] = obj3[key]
  }
  console.log(obj4); // {name: '李四', age: 20}

通第二种方法一样,只能深拷贝对象的第一层,若对象内元素为对象将不能进行深度copy

4、Object.assign()对象合并

  let obj = { name: '张三', age: 20 }
  let obj1 = Object.assign({}, obj)
  console.log(obj1); // {name: '张三', age: 20}

只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度copy

5、循环递归进行copy

function deepClone(obj, newObj) {
    var newObj = newObj || {}
    for (const key in obj) {
      if (typeof obj[key] == 'object') {
        newObj[key] = (obj[key].constructor === Array) ? [] : {}
        deepClone(obj[key], newObj[key])
      } else {
        newObj[key] = obj[key]
      }
    }
    console.log(newObj); // {name: '张三', age: 20}
    return newObj
  }
  let obj = { name: '张三', age: 20 }
  deepClone(obj)

循环递归的时候要设置临界值(typeof obj[key] == 'object'),避免造成死循环。

使用循环递归的方式可以处理对象嵌套数组或者对象的问题。相当于for in遍历copy的优化版本。

扩展方法

1、通过jQuery的extend方法实现深拷贝

var array = [1,2,3,4];
var newArray = $.extend(true,[],array);

2、lodash函数库实现深拷贝

lodash很热门的函数库,提供了 lodash.cloneDeep()实现深拷贝

\