怎么使用javascript深度拷貝一個數(shù)組
有兩種數(shù)組拷貝類型:淺拷貝 & 深拷貝。淺拷貝只會拷貝數(shù)組的第一層,剩下的會引用。如果你需要一個嵌套的數(shù)組的拷貝,那需要你去深度拷貝這個數(shù)組。深拷貝,選擇JSON方法或者Lodsh庫吧
const numbers = [1, [2], [3, [4]], 5]; // Using JavaScript JSON.parse(JSON.stringify(numbers)); // Using Lodash _.cloneDeep(objects);
數(shù)組是引用類型
為了搞清楚為什么有兩種類型的拷貝,我們來深度了解一下基礎(chǔ)知識然后解釋什么是引用類型。
與原始類型(number、string)不同,數(shù)組是引用類型。這意味著當(dāng)你把一個數(shù)組賦值給一個變量,你是將數(shù)組的內(nèi)存地址而非數(shù)組本身賦給變量。
拷貝值類型
這里沒什么大不了的,我們創(chuàng)建一個value的拷貝。當(dāng)我們改變valueCopy的值,它不會影響原來的value值。同理,當(dāng)我們改變原來的值它也不會影響拷貝后的值。很好👍
let value = 3; let valueCopy = value; // create copy console.log(valueCopy); // 3 // Change valueCopy valueCopy = 100 console.log(valueCopy); // 100 // ✅ Original NOT affected console.log(value); // 3
拷貝引用類型
好的,這里就會有點(diǎn)奇怪了!我們用同樣的方法拷貝數(shù)組。
let array = [1,2,3]; let arrayCopy = array; // create copy console.log(arrayCopy); // [1,2,3]; // Change 1st element of the array arrayCopy[0] = '👻'; console.log(arrayCopy); // [ '👻', 2, 3 ] // ❌Original got affected console.log(array); // [ '👻', 2, 3 ]
為什么原來的數(shù)組也受到了影響呢?好了,是因?yàn)椋耗憧截惖牟皇悄憧截惖?。說人話,意思就是你拷貝的只是指向數(shù)組內(nèi)存空間的指針。引用類型不包含值,它們是指向內(nèi)存中值的指針。
拷貝引用類型的方法
解決方法就是拷貝值而不是指針。
let array = [1,2,3]; let arrayCopy = [...array]; // create TRUE copy console.log(arrayCopy); // [1,2,3]; // Change 1st element of the array arrayCopy[0] = '👻'; console.log(arrayCopy); // [ '👻', 2, 3 ] // ✅ Original NOT affected console.log(array); // [ 1, 2, 3 ]
淺 & 深 拷貝
當(dāng)我使用展開擴(kuò)展符號...來拷貝一個數(shù)組,我只是淺拷貝了一個數(shù)組。如果數(shù)組是嵌套或者多維的,這就不奏效了。
let nestedArray = [1, [2], 3]; let arrayCopy = [...nestedArray]; // Make some changes arrayCopy[0] = '👻'; // change shallow element arrayCopy[1][0] = '💩'; // change nested element console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ] // ❌ Nested array got affected console.log(nestedArray); // [ 1, [ '💩' ], 3 ]
如上,淺拷貝首層數(shù)組表現(xiàn)良好,然而,更改了嵌套數(shù)組元素,原始數(shù)組也受到影響💩。為了解決這個問題,就要用到深拷貝了。
let nestedArray = [1, [2], 3]; let arrayCopy = JSON.parse(JSON.stringify(nestedArray)); // Make some changes arrayCopy[0] = '👻'; // change shallow element arrayCopy[1][0] = '💩'; // change nested element console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ] // ✅ Nested array NOT affected console.log(nestedArray); // 1, [ 2 ], 3 ]
所以,這就完事了嗎?要不要手寫一個深拷貝引用類型的方法?
const deepClone = obj => { const isObject = args => (typeof args === 'object' || typeof args === 'function') && typeof args !== null if (!isObject) throw new Error('Not Reference Types') let newObj = Array.isArray(obj) ? [...obj] : { ...obj } Reflect.ownKeys(newObj).map(key => { newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] }) return newObj }
文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,
相關(guān)文章
JavaScript實(shí)現(xiàn)LRU緩存的三種方式詳解
LRU全稱為Least?Recently?Used,即最近使用的。針對的是在有限的內(nèi)存空間內(nèi),只緩存最近使用的數(shù)據(jù)(即get和set的數(shù)據(jù))。本文介紹了JavaScript實(shí)現(xiàn)LRU緩存的三種方式,需要的可以參考一下2022-06-06DOM_window對象屬性之--clipboardData對象操作代碼
clipboardData 對象提供了對于預(yù)定義的剪貼板格式的訪問,以便在編輯操作中使用。2011-02-02

微信小程序開發(fā)之map地圖組件定位并手動修改位置偏差

js實(shí)現(xiàn)隨機(jī)點(diǎn)名系統(tǒng)(實(shí)例講解)

微信小程序 配置頂部導(dǎo)航條標(biāo)題顏色的實(shí)現(xiàn)方法