=
只能 Copy Array 的 Reference,而非真正 Clone Array,本文整理出 4 種方式,並詳細分析其特色。
Version
macOS Mojave 10.14.5
VS Code 1.37.0
Quokka 1.0.240
ECMAScript 2015
Ramda 0.26.1
Assignment Operator
import { equals } from 'ramda';
let arr1 = [1, 2, 3];
let arr2 = arr1;
arr1 === arr2; // ?
equals(arr1, arr2); // ?
直覺會使用 =
assignment operator。
使用 ===
判斷為 true
,可見 arr1
與 arr2
的 reference 相同,因此為 copy reference,並非 clone array。
使用 Ramda 的 equals()
判斷為 true
,由於 arr1
與 arr2
的 reference 相同,value 當然相同。
Array.prototype.slice()
import { equals } from 'ramda';
let arr1 = [1, 2, 3];
let arr2 = arr1.slice();
arr1 === arr2; // ?
equals(arr1, arr2); // ?
在 ES5 若要 clone array,必須使用 Array.prototype.slice()
。
Array.prototype.slice([begin[, end]])
將整個 array 或部分 array 做 shallow clone
begin
:起始 indexend
:結束 index (不包含)
若不指定 begin
與 end
,則相當於 clone 整個 array。
若指定 begin
與 end
,則 clone 部分 array。
使用 ===
判斷為 false
,可見 arr1
與 arr2
的 reference 並不相同,因此並非 copy reference。
使用 Ramda 的 equals()
判斷為 true
,可見 arr1
與 arr2
的 value 相同,因此為 clone array。
Array.from()
import { equals } from 'ramda';
let arr1 = [1, 2, 3];
let arr2 = Array.from(arr1);
arr1 === arr2; // ?
equals(arr1, arr2); // ?
ES6 引進 Array.from()
,專門負責將 array-like object 與 iterable 轉成 array。
因為 array 亦是 iterable,因此也能用於 Array.from()
,由於回傳為新 array,意外地也算 clone array。
Spread Operator
import { equals } from 'ramda';
let arr1 = [1, 2, 3];
let arr2 = [...arr1];
arr1 === arr2; // ?
equals(arr1, arr2); // ?
ES6 亦引進了 ...
spread operator,可將 array element 展開,若放在 []
內,也能實現 clone array。
Ramda
import { clone } from 'ramda';
let arr1 = [
1,
[3, 4],
];
let arr2 = [...arr1]; // ?
let arr3 = clone(arr1); // ?
arr1 === arr2; // ?
arr1 === arr3; // ?
arr1[1] === arr2[1]; // ?
arr1[1] === arr3[1]; // ?
無論 Array.prototype.slice()
、Array.from()
或 spread operator,都只能對 array 做 shallow clone,也就是第一層 array 為 clone,第二層之後 array 為 copy reference。
arr1
內包含 nested array [3, 4]
,其中 arr2
使用 ...
,而 arr3
使用 Ramda 的 clone()
。
無論使用 ...
或 clone()
,arr2
與 arr3
的 reference 皆與 arr1
不同。
arr2[1]
與arr1[1]
的 reference 相同,顯然...
是 shallow clonearr3[1]
與arr1[1]
的 reference 不同,顯然clone()
deep clone
Conclusion
- 若要 shallow clone,則
...
spread operator 是可讀性最高寫法;若要 deep clone,則要使用 Ramda 的clone()
Reference
Samantha Ming, ES6 Way to Clone an Array
MDN, Array.prototype.slice()
MDN, Array.from()
MDN, Spread syntax