Array構造的數組使用map爲什麼失效?

譯者按: Array函數構造的數組沒有初始化索引,沒法使用map函數。javascript

爲了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原做者全部,翻譯僅用於學習。前端

示例

假設你須要生成一個從0到99的數組。你要怎麼作呢?下面是一種解法:java

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']
複製代碼

它實際上等價於:app

{
  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監控,歡迎各位老鐵體驗!

相關文章
相關標籤/搜索