JS: 淺拷貝vs深拷貝 | 刷題打卡

1. 概念

在JavaScript中,拷貝通常是指變量的複製過程。前端

對於簡單類型,拷貝就是直接賦值的過程;函數

對於複雜類型,淺拷貝是指複製對象的引用地址的過程。若是修改了源對象的某個屬性,因爲引用相同,因此目標對象的屬性也會被改變。post

2. 測試

// 測試1 function test() { var obj = { id: 1, name: 'Tom', props: { age: 18, }, color: ['red', 'green'], }; const res = copy(obj); obj.props.age = 20; // 修改原對象的屬性值,觀察目標對象是否受影響 console.log(res.props.age === 20); // true // 表示目標對象受到影響 } 複製代碼

3. 實現

function copy(source) { let res = {}; for (const key in source) { res[key] = source[key]; } return res; } 複製代碼

2、深拷貝

1. 概念

對於複雜類型,淺拷貝是指徹底複製一個全新的對象,修改原對象的屬性,不會影響目標對象。由於複製出來的2個對象引用不一樣,也就是指向內存的地址不一樣。測試

2. 測試

function test() { var obj = { id: 1, name: 'Tom', props: { age: 18, }, color: ['red', 'green'], }; let res = deepCopy(obj); obj.props.age = 20; // 修改原對象的屬性值,觀察目標對象是否受影響 console.log(res.props.age === 18); // true // 表示不受影響 } 複製代碼

3. 實現

// 初版 function deepCopy(target, source) { for (const key in source) { const item = source[key]; if (Array.isArray(item)) { target[key] = []; deepCopy(target[key], item); } else if (typeof element === 'object') { target[key] = {}; deepCopy(target[key], item); } else { target[key] = item; } } } 複製代碼

仔細觀察發現第一個版本有不少冗餘的代碼,改造一下:ui

// 第二版 function deepCopy(target, source) { for (const key in source) { const item = source[key]; if (typeof item === 'object') { deepCopy(Array.isArray(target[key]) ? [] : {}, item); } else { target[key] = item; } } } 複製代碼

3、總結

  • 若是一個已知對象,屬性都是簡單類型,能夠經過 JSON.parse(JSON.stringify(source))來實現深拷貝spa

  • 可是若是原對象中有函數、日期、正則等複雜類型的屬性,轉換後會出現屬性丟失問題code

  • 產生這種問題的根本緣由是 JSON不支持這些上述複雜類型,具體解釋能夠看這裏對象

// 測試 JSON方式的深拷貝 function test() { var obj = { name: 'bird', speak: function() { console.log('ji ji ji') } } let res = deepClone(obj); console.log(res.speak); // undefined // 表示方法屬性丟失了 } function deepClone(source) { return JSON.parse(JSON.stringify(source)); }

本文首發於前端黑洞網,博客園同步跟新

相關文章
相關標籤/搜索