Javascript深拷贝

什么是深拷贝

创建一个新的对象或数组时,将原对象/数组的“值”拷贝,而不是“引用”。

深拷贝

  1. 数组拷贝
    不存在多层嵌套的情况下,直接for遍历、slice()、concat(),都是可行的。

  2. JSON.parse(JSON.stringify(XXX))

var a = [
{  name: ' dadad'  },
{  age: 18 }
];
var copy_a = JSON.parse(JSON.stringify(a))
copy_a[0].name = 'ddd'
console.log(a);//   dadad
console.log(copy_a);//   ddd

通过JSON.stringify()序列化对象;序列化的作用就是存储对象(对象本身存储的只是一个地址映射,如果断电,对象将不复存在,因此需将对象的内容转换成字符串的形式再保存在磁盘上 ),再通过JSON.parse反序列化,申请新的地址,从而copy了对象。
但需要注意的是

  • 如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象

  • 如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;

  • 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null

  • 如果obj中存在循环引用的情况也无法正确实现深拷贝

  1. Object.assign({},XXX)
var a = {b:undefined,c:NaN,d:'sdsd',e:function(){}}
var copy_a = Object.assign({},a)
copy_a.b = 2;
console.(copy_a);

利用ES6中的Object.assign方法,但是当obj是多层嵌套对象时,对于第一层以外的对象,则依然只是引用。

var a = {
  name: {
        first: 'sss' ,
  }
}
var copy_a = Object.assign({},a)
copy_a.name.first = '2'
console.log(a.name.first) //  2

但需要copy的对象只是一层时,用Object.assign显然会比JSON省心许多。

  1. 递归拷贝
    当需要拷贝的对象又是多层嵌套,又有函数等等,此时就需要我们手动写一个递归拷贝。
function copyFn(obj) {
   if (obj == null) {
        return null
    }
    var result = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] === 'object') {
                result[key] = copyFn(obj[key]);  // 如果是对象,再次调用该方法自身
            } else {
                result[key] = obj[key];
            }
        }
    }
    return result;
}

参考文章:
javascript中的深拷贝和浅拷贝?
JavaScript 实现复杂对象深拷贝(对象值包含函数)

你可能感兴趣的:(Javascript深拷贝)