JavaScript深拷貝與淺拷貝實現(xiàn)詳解
對于基本類型數(shù)據(jù)
可以說都是深拷貝。
對于引用類型數(shù)據(jù)
對于引用類型數(shù)據(jù),淺拷貝 后,因為淺拷貝只拷貝了引用地址,所以兩個對象均使用同一個引用地址,此引用地址指向同一個內(nèi)存即數(shù)據(jù)值。對其中任何一個對象操作會改變引用地址對應(yīng)的數(shù)據(jù)的值。
而 深拷貝 將一個對象從內(nèi)存中完整的拷貝一份出來,從堆內(nèi)存中開辟一個新的區(qū)域存放新對象,且修改新對象不會影響原對象。
問:解構(gòu)賦值是深拷貝還是淺拷貝?
若數(shù)組是一維數(shù)組,則可以看做是深拷貝。
let arr = [1, 2, 3] let copyArr = [...arr] copyArr.push(4) console.log(arr, copyArr)
若數(shù)組是多維數(shù)組,則是淺拷貝。
let arr2 = [[1, 2, 3], [9, 0, 6]] let copyArr2 = [...arr2] copyArr2[0].push(77) console.log(arr2, copyArr2)
注: 簡單賦值只是復(fù)制了引用地址:
const a1 = [1, 2]; const a1Copy = a1; a1Copy[0] = 9; console.log(a1) // [9, 2] console.log(a1Copy) // [9, 2]
若不用 擴展運算符拷貝, ES5 中用變通方法來拷貝數(shù)組
const a1 = [1, 2]; const a1Copy = a1.concat(); a1Copy[0] = 9; a1 // [1, 2]
實現(xiàn)深拷貝
簡單版
在不使用第三方庫的情況下,想要深拷貝一個對象
const newObj = JSON.parse(JSON.stringify(oldObj))
局限性:
- 無法實現(xiàn)對RegExp、Date、Set、Map等特殊對象的克隆
- 無法拷貝函數(shù)
- 會拋棄對象的constructor,所有的構(gòu)造函數(shù)會指向Object
- 對象有循環(huán)引用,會報錯
夠用版
使用遞歸,拷貝數(shù)組或?qū)ο蟆?/p>
function deepClone(source) { // 定義結(jié)果對象或數(shù)組 const targetObj = source.constructor === Array ? [] : {} // 遍歷key for (let keys in source) { // 如果key是對象的自有屬性 // hasOwnProperty()查找一個對象是否有某個屬性,但是不會去查找它的原型鏈。 if (source.hasOwnProperty(keys)) { // 如果是引用類型 if (source[keys] && typeof source[keys] === 'object') { // 遞歸 targetObj[keys] = deepClone(source[keys]) } else { // 如果是基本類型 targetObj[keys] = source[keys] } } } return targetObj }
- 關(guān)于其他情況,如解決循環(huán)引用、拷貝特殊對象、拷貝函數(shù)的情況不常見,本文就不寫解決這些問題的代碼啦。
- 在實際開發(fā),克隆數(shù)據(jù)還是使用第三方庫更好。
新發(fā)現(xiàn)個原生深拷貝的方法,
structuredClone
全局的 structuredClone() 方法使用結(jié)構(gòu)化克隆算法將給定的值進(jìn)行深拷貝 。
適用 H5;
Error 以及 Function 對象是不能被結(jié)構(gòu)化克隆算法復(fù)制等等缺點。
詳情看 MDN:傳送門
let obj = { a: [1, 2], b: "eee", c: 3, }; let cloneObj = structuredClone(obj); cloneObj.a[0] = 10; console.log(cloneObj.a[0]); // 10 console.log(obj.a[0]); // 1
到此這篇關(guān)于JavaScript深拷貝與淺拷貝實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)JS深拷貝與淺拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
開源免費天氣預(yù)報接口API及全國所有地區(qū)代碼(國家氣象局提供)
這篇文章主要介紹了開源免費天氣預(yù)報接口API及全國所有地區(qū)代碼(國家氣象局提供)的相關(guān)資料,需要的朋友可以參考下2016-12-12BootStrap Table后臺分頁時前臺刪除最后一頁所有數(shù)據(jù)refresh刷新后無數(shù)據(jù)問題
這篇文章主要介紹了BootStrap Table后臺分頁時前臺刪除最后一頁所有數(shù)據(jù)refresh刷新后無數(shù)據(jù)問題,需要的朋友可以參考下2016-12-12JS實現(xiàn)數(shù)組去重方法總結(jié)(六種方法)
這篇文章給大家總結(jié)下JS實現(xiàn)數(shù)組去重方法(六種方法),面試中也經(jīng)常會遇到這個問題。文中給大家引申的還有合并數(shù)組并去重的方法,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2017-07-07JavaScript變量聲明var,let.const及區(qū)別淺析
這篇文章主要介紹了JavaScript變量聲明var,let.const及區(qū)別淺析,需要的朋友可以參考下2018-04-04詳解JavaScript私有類字段和TypeScript私有修飾符
這篇文章主要介紹了JavaScript私有類字段和TypeScript私有修飾符,對私有類感興趣的同學(xué),可以參考下2021-04-04JavaScript中的執(zhí)行環(huán)境和作用域鏈
這篇文章主要介紹了JavaScript中的執(zhí)行環(huán)境和作用域鏈,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下2020-09-09JavaScript實現(xiàn)圖片懶加載(Lazyload)
這篇文章主要介紹了JavaScript實現(xiàn)圖片懶加載(Lazyload)的相關(guān)資料,需要的朋友可以參考下2016-11-11微信小程序 scroll-view 水平滾動實現(xiàn)過程解析
這篇文章主要介紹了微信小程序 scroll-view 水平滾動實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10