標籤:全域對象 屬性 first 深複製 除了 實現 || boolean objc
原文
簡書原文:https://www.jianshu.com/p/3d930756dd8f
大綱
前言
1、對深拷貝和淺拷貝的初步認識
2、深拷貝和淺拷貝的區別
3、淺拷貝存在的缺陷
4、深拷貝的實現方式
前言
對於很多初次接觸JavaScript的讀者來說,想要實現對象的拷貝/複製,就是單純的使用指派陳述式(=)來實現需求。但是,這樣的方式是不全面的,這樣的方法對於簡單類型的資料來說是沒有問題的,但是如果是對於像對象這樣的複雜的資料類型來說,這樣的實現方式有就會給你帶來意想不到的問題。那麼,如果不能簡單的用指派陳述式實現對象的拷貝(複製),我們應該用什麼樣的方式呢?這個,就是深拷貝和淺拷貝的意義所在了。
1、對深拷貝和淺拷貝的初步認識
深拷貝和淺拷貝只針對像 Object, Array 這樣的複雜物件的。簡單來說,淺拷貝只拷貝一層對象的屬性,而深拷貝則遞迴拷貝了所有層級。
對於字串類型,淺拷貝是對值的複製,對於對象來說,淺拷貝是對對象地址的複製,並沒有開闢新的棧,也就是複製的結果是兩個對象指向同一個地址,修改其中一個對象的屬性,則另一個對象的屬性也會改變,而深拷貝則是開闢新的棧,兩個對象對應兩個不同的地址,修改一個對象的屬性,不會改變另一個對象的屬性。
2、深拷貝和淺拷貝的區別
雖然兩者都是對內容的拷貝,但是拷貝的內容的不同是區分兩者的關鍵,而這個不同主要體現在對Object和Array這樣的複雜物件。最直接的原因是諸如字串這樣簡單的類型的拷貝就是內容的複製,並不會有別的什麼深層次的東西,但是對於Objcet和Array這樣複雜的類型,主要是由於對象的複製是基於對對象的地址的複製而不是整體內容的複製(對象包含了key ,value)。
簡而言之:淺拷貝之後的對象實際上都是同一個對象,而深拷貝之後的對象都是除了內容相同以外完全無關的對象。
3、淺拷貝存在的缺陷
通過一個執行個體來說明使用淺拷貝對對象進行複製會導致哪些問題,從而正確認識使用深拷貝和淺拷貝的重要意義。
var obj = { a:1, arr: [2,3] };var shallowObj = shallowCopy(obj);function shallowCopy(src) { var dst = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst;}/* 導致的結果就是: 對shallowObj對象的更改也會影響到原對象obj,即所謂的牽一髮而動全身。*/shallowObj.arr[1] = 5;obj.arr[1] // = 54、深拷貝的實現方式
以下介紹兩種我平時收集到並且常用的深拷貝的實現方式,希望能對讀者有所協助。
4.1、通過JSON解析解決
針對純 JSON 資料對象的深複製,使用 JSON 全域對象的 parse 和 stringify 方法來實現深複製也算是一個簡單討巧的方法。然而使用這種方法會有一些隱藏的坑,它能正確處理的對象只有 Number, String, Boolean, Array, 扁平對象,即那些能夠被 json 直接表示的資料結構。
var test = { person: { name: { first: ‘chen‘, last: ‘kk‘ }, age: 12 }, interest: [‘book‘, ‘run‘, ‘jump‘]}var result = JSON.parse(JSON.stringify(test))result.interest.push(‘sing‘)console.dir(test)//[‘book‘, ‘run‘, ‘jump‘]console.dir(result)//friend: [‘book‘, ‘run‘, ‘jump‘,‘sing‘]4.2、通過遞迴解析解決
想要獲得多層的資料結構的資料的深拷貝,不得不考慮使用迭代的方式。下列的方法將需要考慮深拷貝的對象、Array資料類型,並不斷的通過迭代判斷來對這兩種類型的資料進行深拷貝。
var china = { nation: ‘中國‘, birthplaces: [‘北京‘, ‘上海‘, ‘廣州‘], skincolr: ‘yellow‘, friends: [‘sk‘, ‘ls‘]}//深複製,要想達到深複製就需要用遞迴function deepCopy(o, c) { var c = c || {} for (var i in o) { if (typeof o[i] === ‘object‘) { //要考慮深複製問題了 if (o[i].constructor === Array) { //這是數組 c[i] = [] } else { //這是對象 c[i] = {} } deepCopy(o[i], c[i]) } else { c[i] = o[i] } } return c}var result = { name: ‘result‘}result = deepCopy(china, result)console.dir(result)
JavaScript的深拷貝和淺拷貝