JavaScript如何深度拷貝一個數組

有兩種數組拷貝類型: 淺拷貝 & 深拷貝淺拷貝只會拷貝數組的第一層,剩下的會引用。若是你須要一個嵌套的數組的拷貝,那須要你去深度拷貝這個數組。 深拷貝,選擇JSON方法或者Lodsh庫吧👍

const numbers = [1, [2], [3, [4]], 5];
// Using JavaScript
JSON.parse(JSON.stringify(numbers));
// Using Lodash
_.cloneDeep(objects);
複製代碼

數組是引用類型

爲了搞清楚爲何有兩種類型的拷貝,咱們來深度瞭解一下基礎知識而後解釋什麼是引用類型。數組

與原始類型(number、string)不一樣,數組是引用類型。這意味着當你把一個數組賦值給一個變量,你是將數組的內存地址而非數組自己賦給變量。 😱bash

拷貝值類型

這裏沒什麼大不了的,咱們建立一個value的拷貝。當咱們改變valueCopy的值,它不會影響原來的value值。同理,當咱們改變原來的值它也不會影響拷貝後的值。很好👍ui

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
複製代碼

拷貝引用類型

好的,這裏就會有點奇怪了!咱們用一樣的方法拷貝數組。spa

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 ]
複製代碼

爲何原來的數組也受到了影響呢?好了,是由於:你拷貝的不是你拷貝的。說人話,意思就是你拷貝的只是指向數組內存空間的指針。引用類型不包含值,它們是指向內存中值的指針指針

拷貝引用類型的方法

解決方法就是拷貝值而不是指針。code

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 ]
複製代碼

淺 & 深 拷貝

當我使用展開擴展符號...來拷貝一個數組,我只是淺拷貝了一個數組。若是數組是嵌套或者多維的,這就不奏效了。cdn

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 ]
複製代碼

如上,淺拷貝首層數組表現良好,然而,更改了嵌套數組元素,原始數組也受到影響💩。爲了解決這個問題,就要用到深拷貝了。blog

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 ]
複製代碼

因此,這就完事了嗎?要不要手寫一個深拷貝引用類型的方法?ip

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
}
複製代碼

✅ ✅ ✅內存

相關文章
相關標籤/搜索