淺拷貝是對象共用一個內存地址,對象的變化相互影響。好比常見的賦值引用就是淺拷貝:es6
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' }
簡單理解深拷貝是將對象放到一個新的內存中,兩個對象的改變不會相互影響。json
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() 算是對 深拷貝的一個無腦實現,看例子:code
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()仍是須要謹慎使用。內存
後續再補充深拷貝實現思想。。。。underscore
最後在補充一點數組的深拷貝和淺拷貝,同對象同樣數組的淺拷貝也是改變其中一個會相互影響,好比:
let srcArr = [1, 2, 3]; let copyArr = srcArr; copyArr[0] = '0'; console.log('srcArr', srcArr); // ['0', 2, 3]
可是數組的深拷貝方法要相對簡單一些能夠理解爲數組方法中那些會改變原數組的方法,好比