Array 可能跟你想的不一樣(下)

osk2
osk2
Nov 4 · 5 min read
Photo by Bharat Patil on Unsplash

怕你還沒看過上集還是先來個前情提要

上集解釋了 new Array() 與 [] 之間的差異,還有使用 new Array() 時要注意的地方

const ary = [undefined, undefined, undefined];ary.forEach(v => {
console.log(v);
});
// 印出三次 undefined
const ary2 = new Array(3);
ary3.forEach(v => {
console.log(v);
});
// 這裡卻什麼都沒印出來

這集就來好好解釋一下 forEach() 是如何運作的,為何上面這段程式沒有如我們想像的執行

Array.prototype.forEach() 如何運作?

要回答這個問題最好的方式就是直接看 ECMAScript 是如何實作 forEach() 的

首先我們到 ECMAScript 查查定義

裡頭提到了 forEach() 的每個步驟

ECMAScript 對 Array.prototype.forEach() 的步驟詳解

我概略列出裡頭跟我們有關的重點:

  1. 先找出陣列的長度(length 屬性)
  2. 開始 while 迴圈
  3. 並檢查陣列是否有名為目前索引值的屬性
  4. 如果上面的條件成立就呼叫 callback(否則什麼事都不做)
  5. 迴圈執行完畢返回 undefined

重點在第三行,還記得上集我們介紹過,用 new Array(3) 建立的陣列只有 length 屬性嗎?

假設目前迴圈第一次執行,接著會查詢 ary[0] 是否存在,結果會是 undefined,也就不會呼叫 callback,這也是為什麼迴圈看起來沒有執行的原因(實際上還是有,只是從來沒有呼叫 callback)

謎題終於解開啦,只是陣列 prototype 中的方法都是類似的處理方式嗎?

同場加映

在上集結尾提到了 fill() 和 join()

new Array(10).join(' ');new Array(3).fill('5566');

你可能又會好奇:難道只有 length 的陣列在這裡又有用途了嗎?

沒錯,先來看看 Array.prototype.join() 的解釋:

ECMAScript 對 Array.prototype.join() 的步驟詳解

一開始會建立一個空字串 R,並在迴圈中依序將每個值與分隔符號(Seperator)附加到 R,最後回傳這個字串

在我們的例子中,陣列中每個值都是 undefined,在 7.c 會被轉為空值,因此在迴圈中每次就只會附加分隔符號到 R,也就是空格,所以最終我們會得到一個全是空格的字串

至於為何 new Array(10) 只產生九個空格呢?好好把步驟 7 再看一次吧!

而 Array.prototype.fill() 也是類似步驟,詳情可以自行參閱 ECMAScript

小技巧

前面提到在 forEach() 執行步驟中,只要有 length 和相對應的屬性就能順利執行

這時聰明的你就會想到:那我能自己建立一個類陣列(Array-like)的物件,然後借用一下 forEach() 強大的功能嗎?

當然可以!

const fakeArray = {  "0": 1,  // 記得陣列索引從 0 開始
"1": 2,
"length": 2,
};Array.prototype.forEach.call(fakeArray, console.log);
/*
執行結果
1 0 {0: 1, 1: 2, length: 2}
2 1 {0: 1, 1: 2, length: 2}
*/

這集大概4醬,如果有哪裡解釋得不好,甚至是錯誤,請一定要告訴我 🙏

然後雖然不知道拍手可以幹嘛,不過喜歡的話還是滿足一下我的虛榮吧 👏👏

References

osk2

Written by

osk2

Just a geek.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade