JS中的陣列複製問題

懶散的小樂發表於2020-08-03

JS中的陣列複製問題

前言

首先提到複製,也就是拷貝問題,就必須要明確淺拷貝和深拷貝。

  • 淺拷貝:B由A複製而來,改變B的內容,A也改變
  • 深拷貝:B由A複製而來,改變B的內容,A的內容不會改變

總的來說就是,基於引用物件的概念,淺拷貝拷貝的是地址,深拷貝直接對值進行了拷貝

那麼在JS的陣列中,哪些複製是淺拷貝的?哪些又是深拷貝的呢?這裡做一個學習總結。

陣列複製

直接賦值符號 “=” 複製

let arr1 = [2,3,4,5,6];
let arr2 = arr1;
arr2.push(12);
console.log(arr1); //[2, 3, 4, 5, 6, 12]
console.log(arr2); //[2, 3, 4, 5, 6, 12]

可以看到通過賦值符號 “=” 複製是淺拷貝。

擴充套件

陣列屬於引用資料型別,那麼我們可以猜測,通過 賦值符號 “=” 賦值的引用資料型別的變數的複製都是淺拷貝,驗證如下:

let obj1 = {value:23};
let obj2 = obj1;
obj2.value = 12;
console.log(obj1);  //{value: 12}
console.log(obj2);  //{value: 12}

那麼值(基礎)資料型別呢?

let num1 = 23;
let num2 = num1;
num2 = 12;
console.log(num1); //23
console.log(num2); //12

可以看到 基礎資料型別通過賦值符號 “=” 的複製是深拷貝的,但要注意,如果你通過物件的方式進行定義的話,那麼基礎資料型別也會變成物件,物件的直接複製僅僅只複製了地址。

let num1 = new Number(23);
let num2 = num1;
num2 = 12;
console.log(num1); //23
console.log(num2); //12

陣列中的複製函式

我們知道,js提供了很多陣列複製的方法,例如拆分操作符(...),map函式,concat函式,slice函式,這些方法都可以進行陣列的複製,那麼今天就一起總結下哪些複製是淺拷貝的,哪些是深拷貝的。

let arr1 = [2,3,4,5,6];
arr2 = [...arr1];
arr2.shift();
console.log(arr1); //[2, 3, 4, 5, 6]
console.log(arr2); //[3, 4, 5, 6]

可以看到通過拆分操作符進行的複製是深拷貝的,arr2指向的是一個新的地址

let arr1 = [2,3,4,5,6];
arr2 = arr1.map(item=>item);
arr2.shift();
console.log(arr1); //[2, 3, 4, 5, 6]
console.log(arr2); //[3, 4, 5, 6]
let arr1 = [2,3,4,5,6];
arr2 = arr1.concat();
arr2.shift();
console.log(arr1); //[2, 3, 4, 5, 6]
console.log(arr2); //[3, 4, 5, 6]
let arr1 = [2,3,4,5,6];
arr2 = arr1.slice();
arr2.shift();
console.log(arr1); //[2, 3, 4, 5, 6]
console.log(arr2); //[3, 4, 5, 6]

經過驗證,拆分操作符(...),map函式,concat函式,slice函式的複製均為深拷貝。

相關文章