Array.forEach()
- 只適用於 Array (類陣列也可以)
- 將陣列內的每個元素,皆傳入並執行給定的函式
- 不像 map() 或 reduce(), forEach 最後一個值一定會回傳 undefined
- forEach 是不可鏈接的
1 | arr.forEach(function callback(currentValue[, index[, array]]) { |
參數
- currentValue: 代表目前被處理中的 Array 之中的那個元素。
- index (optional): 代表目前被處理中的 Array 之中的那個元素的index.
- array (optional): 呼叫 forEach() 方法的那個 Array 本身,也就是上面語法中的 arr。
- thisArg (optional): 執行 callback 回呼函式的 this(即參考之 Object)值。
thisArg 的用法範例
- 如果是使用箭頭函式,可以直接忽略 thisArg,因為箭頭函式會直接綁定 this。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
};
const obj = new Counter();
obj.add([2, 5, 9]);
obj.count; // 3
obj.sum; // 16
for…in
- for…in 迴圈只迭代 enumerable properties。
- for…in 迴圈迭代物件屬性的順序是隨意的。
- for…in 不應該用來迭代一個索引順序很重要的陣列。 陣列索引只是以整數命名的可列舉屬性,其他方面等同於一般物件屬性。 無法擔保 for…in 以特定順序傳回索引,並且它將傳回全部可列舉屬性,包括非整數名的,以及繼承而來的可列舉屬性。如果順序是重要的,那應該要考慮使用 forEach 或 for…of。
1 | for (variable in object) { |
參數
- variable: A different property name is assigned to variable on each iteration.
object - Object: whose enumerable properties are iterated.
用法
1 | var obj = {a: 1, b: 2, c: 3}; |
for…of
- for…of 會 loop through 可迭代的物件(包括: String, Array, Array-like arguments, or NodeList objects, TypedArray, Map and Set, and user-defined iterables)
1 | for (variable of iterable) { |
參數
- variable: On each iteration a value of a different property is assigned to variable.
- iterable: Object whose iterable properties are iterated.
用法
1 | let iterable = [10, 20, 30]; |
for…in VS for…of
以下節錄自 MDN,因為無法很好的翻成中文,英文的說明也比較簡潔易懂。
- Both for…in and for…of statements iterate over something. The main difference between them is in what they iterate over.
- The for…in statement iterates over the enumerable properties of an object, in an arbitrary order.
- The for…of statement iterates over data that iterable object defines to be iterated over.
example
1 | Object.prototype.objCustom = function() {}; |
這個例子可以很清楚地看出兩者的不同點。
一段一段拆分出來看。
1 | Object.prototype.objCustom = function() {}; |
上面這段 code,Object 和 Array 的原型分別加進了 objCustom. arrCustom。
因此,iterable 這個陣列也因為繼承和原型鏈的關係繼承了這兩個屬性。
1 | for (let i in iterable) { |
接著,使用 for…in 對 iterable 做迭代。它並不會 log 出 3,5,7 或是 'hello',因為他們都不是 enumerable 的屬性。
但會 log 出陣列的索引質以及 objCustom 和 arrCustom。0, 1, 2, "foo", "arrCustom", "objCustom"。他們都是 enumerable 的屬性。
1 | for (let i in iterable) { |
這個迴圈和上一段的迴圈是很相像的,不過加入了一個 hasOwnProperty 條件檢查迭代的 enumerable 屬性是不是物件自有的不是繼承而來的。如果是,就 log 出來。
屬性 0, 1, 2, "foo" 都是 iterable 自有的屬性所以會顯示。但 arrCustom, objCustom 是繼承來的,就不會被 log 出來。
1 | for (let i of iterable) { |
這個迴圈迭代並 log 出 iterable作為一個可迭代的物件迭代後回傳的 value。其中並不包含該物件的其他屬性。
什麼是 Enumerable properties ?
一直在說 enumerable properties,究竟它是什麼?
enumerable 的中文是 - 可列舉的。
可列舉的屬性?又是指什麼?
根據 MDN 的解釋,
Enumerable properties are those properties whose internal [[Enumerable]] flag is set to true, which is the default for properties created via simple assignment or via a property initializer.
Jabascript 物件的屬性它們自己內部還有屬性,其中一個內部的屬性就是 enumerable。
而該 enumerable 屬性被設為 true 的屬性,就可稱是可迭代屬性。(有點饒口)
如果想知道的更精確,可以閱讀 MDN 的文件。
參考文章
forEach MDN
for…in MDN
for…of MDN
“foreach” vs “for of” vs “for in” in JavaScript