若我們想指定特定長度建立 Array,且初始值都相同,在 ECMAScript 並沒有內建 Function,但我們可以自行建立 create()
完成需求。
Version
macOS Catalina 10.15
VS Code 1.39.1
Quokka 1.0.254
Ramda 0.26.1
Wink-fp 0.1.9
Array.prototype.map()
let create = n => init => Array(n).map(() => init);
create(3)(1); // ?
直覺會使用 Array(n)
先建立 length 為 n 的 array,再使用 map()
設定初始值。
但結果會發現不如預期。
因為 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 create = n => init => Array.apply(null, Array(n)).map(() => init);
create(3)(1); // ?
也因為 Array.apply(null, Array(n))
不再是 length 為 n 的 sparse array,因此可繼續使用 map()
設定初始值。
Array.from()
let create = n => init => Array.from({ length : n }, () => init);
create(3)(1); // ?
Array.from()
原本設計讓你以 map()
方式處理 array-like object 或 iterable object。
如
documents
就是典型 array-like object,帶有length
property;而 String、Set、Map 是典型 iterable object,可使用for of
因此我們可使用 { length: n }
代表 Array(n)
,且沒有 empty array 與 hole 問題。
Array.from()
的第二個 argument 為 function,如同 map()
用法。
Wink-fp
import { create } from 'wink-fp';
create(3)(1); // ?
Wink-fp 已經內建 create()
,可直接使用。
create()
Number -> a -> [a]
依特定長度與初始值建立 array
Number
:特定長度
a
:Array 的初始值
[a]
:回傳新的 array
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
Dr.Axel Rauschdayer, Initializing an array with values