javascript对象的浅拷贝、深拷贝和Object.assign要领浅析

对象的浅拷贝:

浅拷贝是对象共用一个内存地址,对象的变化相互影响。比方罕见的赋值援用就是浅拷贝:

let srcObj = {'name': 'lilei', 'age': '20'};
let copyObj = srcObj;
copyObj.age = '22';
console.log('srcObj', srcObj);   // srcObj { name: 'lilei', age: '22' }
console.log('copyObj', copyObj);  // copyObj { name: 'lilei', age: '22' }

对象的深拷贝:

简朴明白深拷贝是将对象放到一个新的内存中,两个对象的转变不会相互影响。

Object.assign()

MDN上如许引见Object.assign(),’Object.assign() 要领用于将一切可罗列的属性的值从一个或多个源对象复制到目的对象。它将返回目的对象’,好吧,并看不出是深拷贝照样浅拷贝,我们来测试一下

let srcObj = {'name': 'lilei', 'age': '20'};
let copyObj2 = Object.assign({}, srcObj, {'age': '21'});
copyObj2.age = '23';
console.log('srcObj', srcObj); //{ name: 'lilei', age: '22' }

看起来好像是深拷贝了,那实在这里let copyObj2 = Object.assign({}, srcObj, {'age': '21'}); 我们把srcObj 给了一个新的空对象。一样目的对象为 {},我们再来测试下:

srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'} };
copyObj2 = Object.assign({}, srcObj);
copyObj2.name = '红';
copyObj2.grade.chi = '60';
console.log('新 objec srcObj', srcObj);  // { name: '明', grade: { chi: '60', eng: '50' } }

从例子中可以看出,转变复制对象的name 和 grade.chi ,源对象的name没有变化,然则grade.chi却被转变了。因而我们可以看出Object.assign()拷贝的只是属性值,假如源对象的属性值是一个指向对象的援用,它也只拷贝谁人援用值。
也就是说,关于Object.assign()而言, 假如对象的属性值为简朴范例(string, number),经由过程Object.assign({},srcObj);获得的新对象为‘深拷贝’;假如属性值为对象或别的援用范例,那关于这个对象而言实际上是浅拷贝的。这是Object.assign()迥殊值得注意的处所。
多说一句,Object.assign({}, src1, src2); 关于scr1和src2之间雷同的属性是直接掩盖的,假如属性值为对象,是不会对对象之间的属性举行兼并的。

深拷贝的完成

有许多第三方库完成了对象的深拷贝,比方罕见的 Jquery 和 underscore ,比较将来的 lodash,完成源码还没仔细剖析,剖析以后再来补充。
不过,假如你没有引入这些库,关于深拷贝另有一个简朴的要领完成

JSON.parse() 和 JSON.stringify()

JSON.parse() 和 JSON.stringify() 算是对 深拷贝的一个无脑完成,看例子:

srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'} };
// copyObj2 = Object.assign({}, srcObj);
copyObj2 = JSON.parse(JSON.stringify(srcObj));
copyObj2.name = '红';
copyObj2.grade.chi = '60';
console.log('JSON srcObj', srcObj); // { name: '明', grade: { chi: '50', eng: '50' } }

可以看到转变copyObj2并没有转变原始对象,完成了基础的深拷贝。
然则用JSON.parse()和JSON.stringify()会有一个题目。
JSON.parse()和JSON.stringify()能正确处理的对象只要Number、String、Array等可以被json示意的数据结构,因而函数这类不能被json示意的范例将不能被正确处理。比方

srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'},
    'hello': function() {console.log('hello')}};
// copyObj2 = Object.assign({}, srcObj);
copyObj2 = JSON.parse(JSON.stringify(srcObj));
copyObj2.name = '红';
copyObj2.grade.chi = '60';
console.log('JSON srcObj', copyObj2); //{ name: '红', grade: { chi: '60', eng: '50' } }

可以看出,经由转换以后,function丧失了,因而JSON.parse()和JSON.stringify()照样须要郑重运用。

后续再补充深拷贝完成头脑。。。。

数组的深拷贝和浅拷贝

末了在补充一点数组的深拷贝和浅拷贝,同对象一样数组的浅拷贝也是转变个中一个会相互影响,比方:

let srcArr = [1, 2, 3];
let copyArr = srcArr;
copyArr[0] = '0';
console.log('srcArr', srcArr); // ['0', 2, 3]

然则数组的深拷贝要领要相对简朴一些可以明白为数组要领中那些会转变原数组的要领,比方

  • concat
  • slice
  • es6 的Array.from
    原文作者:侯贝贝
    原文地址: https://segmentfault.com/a/1190000014107100
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞