示例
假設你需要生成一個從0到99的數組。你要怎麼做呢?下面是一種解法:
const arr = [];for (let i = 0; i < 100; i++) { arr[i] = i;}
如果你和我一樣,看到這種使用傳統的for循環的方式會有點不大習慣了。事實上,我已經好多年不使用for循環寫代碼了。畢竟,各種高階函數,像forEach, map, filter, reduce足以讓我寫出各種漂亮的代碼。
也許你還沒有沉醉於函數式編程的美妙,那麼你會認為上面的解法足矣。不過,如果你用過高階函數編程,你也許就會想:一定還有更加優雅的實現方法。
我的第一直覺就是:首選創建一個長度為100的空數組,然後由map用index去初始化每一個元素。在JavaScript中,你可以用Array構造函數來創建數組:
const arr = Array(100);
接下來你只需要用map就可以解決問題了:
const arr = Array(100).map((_, i) => i);console.log(arr[0] === undefined); // true
可是,為什麼第一個元素不是0而是undefined?
解釋
為了理解為何沒有生效,我需要首先講清楚一個非常重要的技術點。在內部,JavaScript數組實際上是對象,對象裡面的屬性名是數字,對應數組的下標。舉個例子:
['a', 'b', 'c']
它實際上等價於:
{ 0: 'a', 1: 'b', 2: 'c', length: 3}
當你去訪問數組的第0個元素的時候,實際上訪問的是對象中屬性名為0的元素。接下來我們會解釋為何剛剛的代碼沒有效果。
當你使用Array構造函數來新建一個數組,那麼它會創建一個新的數組對象,並且將長度length設定為指定的值。但是,對象裡面沒有數組索引:
{ //no index keys! length: 100}
當你去訪問數組的第0個元素的時候,返回值為undefined。但並不是指第0個元素得值為undefined,而是當數組下標不存在的時候,默認的返回值。
並且如果數組下標不存在的話,其實map函數並沒有真正的對每一個元素執行操作。因為只有當下標存在的時候,map的回調函數才會執行。
解法
因此,我們只需要在數組對象中構造出數組的下標就可以了。最好的方法就是用展開運算符:
const arr = [...Array(100)].map((_, i) => i);console.log(arr[0]);// 0
使用展開運算符後的數組對象:
{ 0: undefined, 1: undefined, 2: undefined, ... 99: undefined, length: 100}
就可以順利使用map函數了。
關於Fundebug
Fundebug專注於JavaScript、微信小程序、小遊戲BUG監控,自從2016年雙十一正式上線,Fundebug已經服務了一年半時間,累計處理了5億+錯誤事件,得到了眾多知名用戶的認可。Fundebug支持主流前端框架的bug監控,歡迎各位老鐵體驗!
補充一個方法:
Array.from({length: 100}, (_, i) => i);
解決。