JavaScript中的深浅复制

什么是深浅复制

  • 浅复制:浅复制就是复制一份引用,所有的引用对象都指向同一份数据,并且都可以修改这份数据.
  • 深复制:所谓”深拷贝”,就是能够实现真正意义上的数组和对象的拷
var a = 5;
var b = a;
b = 1;
console.log(a);//5
console.log(b);//1
var a = {name:tom};
var b = a;
b.name = 'lisa';
console.log(a.name);//lisa
console.log(b.name);//lisa

由上述代码可见,基本类型的赋值是深复制,引用类型的赋值是浅复制

如何实现引用类型深复制

浅复制是非常简单的,那么对于引用类型来说要如何实现深复制呢

  • Object.assign()方法(一层深复制)
var obj = {name:'tom',age:10,like:{fruit:'apple'}};
var newObj = Object.assign({},obj);
console.log(newObj);
obj.name = 'lisa';
obj.like.fruit = 'peach';
console.log(newObj);
//第一个输出结果
{
  age: 10,
  like: [object Object] {
    fruit: "apple"
  },
  name: "tom"
}
//第二个输出结果
{
  age: 10,
  like: [object Object] {
    fruit: "peach"
  },
  name: "tom"
}

我们看到对象的第一层的属性值的修改并不会互相影响,也就是说他们占用的是不同的内存,但是第二层的属性值的修改却会互相影响,所以第二层复制过来得只是对象的引用,他们是指向同一块内存的
因此:Object.assign()方法只实现了对象第一层的深复制,更深层的都是浅复制.

  • JSON对象的json.stringify()方法和json.parse()方法
    • json.stringify():将js对象转换成字符串对象
    • json.parse():将字符串对象转换成js对象
var obj = {name:'tom',age:10,like:{fruit:'apple'}};
var strObj = JSON.stringify(obj);
var jsObj = JSON.parse(strObj);
obj.name = 'lisa';
obj.like.fruit = 'peach';
console.log(jsObj);
//输出结果
{
  age: 10,
  like: [object Object] {
    fruit: "apple"
  },
  name: "tom"
}

我们看到在obj上的修改都不会影响到最终的jsObj,所以结合这两个方法可以轻松实现对象的深复制.

  • 原生js实现深拷贝
    思路:如果对象属性值是基本类型则直接赋值(前边提过,基本类型的赋值属于深拷贝)如果对象是引用类型,则递归至基本类型再赋值
function deepCopy(p,c) {
   if(p === null || typeof p !== "object"){//非引用类型的深拷贝直接赋值
           return p;
       }
    var c = c || {};
    for (var i in p) {//引用类型,遍历属性
        if (typeof p[i] === 'object') { //属性值是引用类型
            c[i] = (p[i].constructor === Array) ? [] : {};//属性值是数组还是对象决定递归时传入的c[i]是[]还是{}
            deepCopy(p[i], c[i]);//递归拷贝
        } else {
            c[i] = p[i];//属性值是基本类型,直接赋值
        }
    }
    return c;
}

var target = {name:'tom',age:1,like:{fruit:['apple','peach']}};
var copyObj =  (deepCopy(target));
console.log(copyObj);
target.name = 'lisa';
target.like.fruit = ['apple'];
console.log(copyObj);
//第一次输出结果
 {
  age: 1,
  like: [object Object] {
    fruit: ["apple", "peach"]
  },
  name: "tom"
}
//第二次输出结果
 {
  age: 1,
  like: [object Object] {
    fruit: ["apple", "peach"]
  },
  name: "tom"
}

我们可以看到上述代码实现了对象的深拷贝,拷贝后两个对象的修改并不会相互影响.

    原文作者:baiying
    原文地址: https://www.jianshu.com/p/68f45be2d4f7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞