若我們想指定特定長度建立 Array,且給定初始值,隨後會自動建立 Sequence,在 ECMAScript 並沒有內建 Function,但我們可以自行建立 generate()
完成需求。
Version
macOS Catalina 10.15
VS Code 1.39.1
Quokka 1.0.256
ECMAScript 2015
Ramda 0.26.1
Wink-fp 0.1.11
Array.prototype.map()
let generate = n => begin => Array(n).map((_, i) => i + begin);
generate(3)(1); // ?
直覺會使用 Array(n)
先建立 length 為 n 的 array,再使用 map()
建立 sequence。
但結果會發現不如預期。
因為 new Array(n)
會建立 length 為 n 的 sparse array,也就是內容為 hole。
map()
會 skip 這些 hole 但保留之,因此回傳原本 array。
Function.prototype.apply()
Array.apply(null, Array(3));
改用 Array.apply()
呼叫 Array()
,也就是 Array.apply(null, [1, 2])
相當於 Array(1, 2)
。
但 Array.apply()
有個特殊功能:將 hole 視為 undefined
處理,因此 Array.apply(null, Array(3))
將回傳 [undefined, undefined, undefined]
。
let generate = n => begin => Array.apply(null, Array(n)).map((_, i) => i + begin);
generate(3)(1); // ?
也因為 Array.apply(null, Array(n))
不再是 length 為 n 的 empty array,因此可繼續使用 map()
建立 sequence。
Array.from()
let generate = n => begin => Array.from({ length: n }, (_, i) => i + begin);
generate(3)(2); // ?
Array.from()
原本設計讓你以 map()
方式處理 array-like object。
如
documents
就是典型 array-like object,帶有length
property
因此我們可使用 { length: n }
代表 Array(n)
,且沒有 empty array 與 hole 問題。
Array.from()
的第二個 argument 為 function,如同 map()
用法。
Conclusion
Array.apply()
巧妙地將 hole 視為undefined
,因此可繼續使用map()
- ES6 的
Array.from()
是很強大 function,可以實作出很多有趣功能 Array.from()
相當於Array()
與map()
合體,還可避開 empty array
Reference
MDN, Array.from()
Dr.Axel Rauschdayer, Array iteration and holes in JavaScript