"for..in"同"for...of"迴圈迷思


todo.js:1 Uncaught (in promise) TypeError: a[Symbol.iterator] is not a function

話說呢排無乜寫文更新呢度,今次就講下我遇到嘅其中一個關於looping嘅問題。
上圖講緊嘅係我喺 近況 #5 中提過嘅To-do List。上星期遇到問題係當超過一頁分頁嘅時候,當我想點擊去第二個分頁嗰陣就會出現錯誤。既然見到係同iterator有關,咁就自然向我堆for-loop埋手啦。結果黎講我選擇咗將所有"for...of" loop轉晒做"for...in" loop。咁到底兩者有咩分別呢?

首先講下"for...in"。Javascript嘅變數入面通常都存在三種屬性:Writable、Configurable同埋Enumerable。當enumerable嘅值係true嗰陣,普通嘅for-loop以至"for...in" loop都可以對變數進行作用。如果enumerable嘅值係false嘅話,相關嘅for-loop就會無視該變數。以下為其中一個例子。

let participant = {
    firstName: 'John',
    lastName: 'Doe',
    age: 17
};

Object.defineProperty(participant, 'age', {enumerable: false});

let containKeys = Object.keys(participant);
console.log(containKeys);    // Output: ['firstName', 'lastName]'

呢段代碼入面,原本participant係有三個設定值:firstName、lastName及age。不過,由於之後定義咗age嘅enumerable值為false,當我哋用Object.keys去拎返participant嘅設定值嘅話只會回傳返firstName同lastName呢兩個值。基本上,(以我嘅理解下)Javascript嘅String屬於Array嘅一種,而Array又屬於Object嘅一種。因此,"for...in" loop可以應用喺包含String及Array在內嘅Object系變數上。

至於"for...of" loop就係屬於ES6嘅產物。佢嘅作用對象主要係iterable collections。咩係iterable collections?但凡變數內包含Symbol.iterator屬性嘅都係iterable collections。根據 MDN 嘅講法,String同Array都有自定義嘅Iterator:

Whenever an object needs to be iterated (such as at the beginning of a for..of loop), its @@iterator method is called with no arguments, and the returned iterator is used to obtain the values to be iterated.


Some built-in types have a default iteration behavior, while other types (such as Object) do not. The built-in types with a @@iterator method are:

Array.prototype[@@iterator]()
TypedArray.prototype[@@iterator]()
String.prototype[@@iterator]()
Map.prototype[@@iterator]()
Set.prototype[@@iterator]()

Mozilla Developer Network (MDN)
由於喺Axios得到嘅回傳資料並非Array變數而係單純Object變數,因此"for...of" loop就無辦法作用喺佢度,從而出現錯誤。不過,如果我將所有回傳返黎嘅資料用Array.from()轉返做Array變數嘅話,亦都可以用"for...of" loop黎處理變數。事實上,由於"for...in" loop會獲得Object key嘅關係,如果你只係想得到value的話就會做成麻煩。

Comparison between "for...in" and "for...of". Reference: for..in versus for..of Loops - bitsofcode

所以點樣去選擇你嘅looping方式都好重要架。

相關閱讀:

Powered by Half-moon Production.

Copyright © 2011-2020 by 泣雨家的雜物房. Version 1.5.2.

"for..in"同"for...of"迴圈迷思


todo.js:1 Uncaught (in promise) TypeError: a[Symbol.iterator] is not a function

話說呢排無乜寫文更新呢度,今次就講下我遇到嘅其中一個關於looping嘅問題。
上圖講緊嘅係我喺 近況 #5 中提過嘅To-do List。上星期遇到問題係當超過一頁分頁嘅時候,當我想點擊去第二個分頁嗰陣就會出現錯誤。既然見到係同iterator有關,咁就自然向我堆for-loop埋手啦。結果黎講我選擇咗將所有"for...of" loop轉晒做"for...in" loop。咁到底兩者有咩分別呢?

首先講下"for...in"。Javascript嘅變數入面通常都存在三種屬性:Writable、Configurable同埋Enumerable。當enumerable嘅值係true嗰陣,普通嘅for-loop以至"for...in" loop都可以對變數進行作用。如果enumerable嘅值係false嘅話,相關嘅for-loop就會無視該變數。以下為其中一個例子。

let participant = {
    firstName: 'John',
    lastName: 'Doe',
    age: 17
};

Object.defineProperty(participant, 'age', {enumerable: false});

let containKeys = Object.keys(participant);
console.log(containKeys);    // Output: ['firstName', 'lastName]'

呢段代碼入面,原本participant係有三個設定值:firstName、lastName及age。不過,由於之後定義咗age嘅enumerable值為false,當我哋用Object.keys去拎返participant嘅設定值嘅話只會回傳返firstName同lastName呢兩個值。基本上,(以我嘅理解下)Javascript嘅String屬於Array嘅一種,而Array又屬於Object嘅一種。因此,"for...in" loop可以應用喺包含String及Array在內嘅Object系變數上。

至於"for...of" loop就係屬於ES6嘅產物。佢嘅作用對象主要係iterable collections。咩係iterable collections?但凡變數內包含Symbol.iterator屬性嘅都係iterable collections。根據 MDN 嘅講法,String同Array都有自定義嘅Iterator:

Whenever an object needs to be iterated (such as at the beginning of a for..of loop), its @@iterator method is called with no arguments, and the returned iterator is used to obtain the values to be iterated.


Some built-in types have a default iteration behavior, while other types (such as Object) do not. The built-in types with a @@iterator method are:

Array.prototype[@@iterator]()
TypedArray.prototype[@@iterator]()
String.prototype[@@iterator]()
Map.prototype[@@iterator]()
Set.prototype[@@iterator]()

Mozilla Developer Network (MDN)
由於喺Axios得到嘅回傳資料並非Array變數而係單純Object變數,因此"for...of" loop就無辦法作用喺佢度,從而出現錯誤。不過,如果我將所有回傳返黎嘅資料用Array.from()轉返做Array變數嘅話,亦都可以用"for...of" loop黎處理變數。事實上,由於"for...in" loop會獲得Object key嘅關係,如果你只係想得到value的話就會做成麻煩。

Comparison between "for...in" and "for...of". Reference: for..in versus for..of Loops - bitsofcode

所以點樣去選擇你嘅looping方式都好重要架。

相關閱讀: