怕你還沒看過上集還是先來個前情提要
上集解釋了 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() 的每個步驟
我概略列出裡頭跟我們有關的重點:
- 先找出陣列的長度(length 屬性)
- 開始 while 迴圈
- 並檢查陣列是否有名為目前索引值的屬性
- 如果上面的條件成立就呼叫 callback(否則什麼事都不做)
- 迴圈執行完畢返回 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() 的解釋:
一開始會建立一個空字串 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醬,如果有哪裡解釋得不好,甚至是錯誤,請一定要告訴我 🙏
然後雖然不知道拍手可以幹嘛,不過喜歡的話還是滿足一下我的虛榮吧 👏👏