for-of
迴圈 for-of
迴圈
for-of
僅適用於可迭代值
const
宣告與 var
宣告
for-of
是 ES6 中的全新迴圈,取代了 for-in
和 forEach()
,並支援新的迭代協定。
使用它來迴圈處理可迭代物件(陣列、字串、Map、Set 等;請參閱章節「可迭代物件和迭代器」)
const
iterable
=
[
'a'
,
'b'
];
for
(
const
x
of
iterable
)
{
console
.
log
(
x
);
}
// Output:
// a
// b
break
和 continue
可在 for-of
迴圈中使用
for
(
const
x
of
[
'a'
,
''
,
'b'
])
{
if
(
x
.
length
===
0
)
break
;
console
.
log
(
x
);
}
// Output:
// a
迴圈處理陣列時,可以同時存取元素及其索引(of
前面的方括號表示我們正在使用解構)
const
arr
=
[
'a'
,
'b'
];
for
(
const
[
index
,
element
]
of
arr
.
entries
())
{
console
.
log
(
`
${
index
}
.
${
element
}
`
);
}
// Output:
// 0. a
// 1. b
迴圈處理 Map 中的 [key, value] 項目(of
前面的方括號表示我們正在使用解構)
const
map
=
new
Map
([
[
false
,
'no'
],
[
true
,
'yes'
],
]);
for
(
const
[
key
,
value
]
of
map
)
{
console
.
log
(
`
${
key
}
=>
${
value
}
`
);
}
// Output:
// false => no
// true => yes
for-of
迴圈 for-of
讓您能迴圈處理可迭代的資料結構:陣列、字串、Map、Set 等。可迭代性如何運作的詳細說明,請參閱章節「可迭代物件和迭代器」。不過,如果您使用 for-of
迴圈,就不需要了解這些細節。
const
iterable
=
[
'a'
,
'b'
];
for
(
const
x
of
iterable
)
{
console
.
log
(
x
);
}
// Output:
// a
// b
for-of
會逐一瀏覽 iterable
的項目,並在執行主體之前將它們指定給迴圈變數 x
。x
的範圍是迴圈,它只存在於迴圈內部。
您可以使用 break
和 continue
for
(
const
x
of
[
'a'
,
''
,
'b'
])
{
if
(
x
.
length
===
0
)
break
;
console
.
log
(
x
);
}
// Output:
// a
for-of
結合了以下優點:
for
迴圈:break
/continue
;可用於產生器forEach()
方法:簡潔的語法for-of
僅適用於可迭代值 of
子句的運算元必須可迭代。這表示如果您想要迴圈處理一般物件,您需要一個輔助函式(請參閱「一般物件不可迭代」)。如果一個值類似陣列,您可以透過 Array.from()
將它轉換為陣列。
// Array-like, but not iterable!
const
arrayLike
=
{
length
:
2
,
0
:
'a'
,
1
:
'b'
};
for
(
const
x
of
arrayLike
)
{
// TypeError
console
.
log
(
x
);
}
for
(
const
x
of
Array
.
from
(
arrayLike
))
{
// OK
console
.
log
(
x
);
}
const
宣告與 var
宣告 如果您對迭代變數使用 const
宣告,每個迭代都會建立一個新的 繫結(儲存空間)。這可以在以下程式碼片段中看到,我們透過箭頭函式儲存 elem
的目前繫結以供稍後使用。之後,您可以看到箭頭函式不會共用 elem
的相同繫結,它們各自有不同的繫結。
const
arr
=
[];
for
(
const
elem
of
[
0
,
1
,
2
])
{
arr
.
push
(()
=>
elem
);
// save `elem` for later
}
console
.
log
(
arr
.
map
(
f
=>
f
()));
// [0, 1, 2]
// `elem` only exists inside the loop:
console
.
log
(
elem
);
// ReferenceError: elem is not defined
let
宣告的工作方式與 const
宣告相同(但繫結是可變的)。
如果您對迭代變數使用 var
宣告,可以清楚地看出事情有何不同。現在所有箭頭函式都會參考 elem
的相同繫結。
const
arr
=
[];
for
(
var
elem
of
[
0
,
1
,
2
])
{
arr
.
push
(()
=>
elem
);
}
console
.
log
(
arr
.
map
(
f
=>
f
()));
// [2, 2, 2]
// `elem` exists in the surrounding function:
console
.
log
(
elem
);
// 2
當您透過迴圈建立函式(例如,新增事件監聽器)時,每個迭代有一個繫結非常有幫助。
您也可以在 for
迴圈(透過 let
)和 for-in
迴圈(透過 const
或 let
)中取得每個迭代的繫結。詳細說明請參閱 變數章節。
到目前為止,我們只看過使用宣告迭代變數的 for-of
。但還有其他幾種形式。
您可以使用現有變數進行迭代
let
x
;
for
(
x
of
[
'a'
,
'b'
])
{
console
.
log
(
x
);
}
您也可以使用物件屬性進行迭代
const
obj
=
{};
for
(
obj
.
prop
of
[
'a'
,
'b'
])
{
console
.
log
(
obj
.
prop
);
}
您還可以使用陣列元素進行迭代
const
arr
=
[];
for
(
arr
[
0
]
of
[
'a'
,
'b'
])
{
console
.
log
(
arr
[
0
]);
}
將 for-of
與解構結合使用,對於可迭代的 [key, value] 成對(編碼為陣列)特別有用。這就是 Map 的用途
const
map
=
new
Map
().
set
(
false
,
'no'
).
set
(
true
,
'yes'
);
for
(
const
[
k
,
v
]
of
map
)
{
console
.
log
(
`key =
${
k
}
, value =
${
v
}
`
);
}
// Output:
// key = false, value = no
// key = true, value = yes
Array.prototype.entries()
也會傳回可迭代的 [key, value] 成對
const
arr
=
[
'a'
,
'b'
,
'c'
];
for
(
const
[
k
,
v
]
of
arr
.
entries
())
{
console
.
log
(
`key =
${
k
}
, value =
${
v
}
`
);
}
// Output:
// key = 0, value = a
// key = 1, value = b
// key = 2, value = c
因此,entries()
提供一種方式讓您可以根據迭代項目在不同位置的不同處理方式。
/** Same as arr.join(', ') */
function
toString
(
arr
)
{
let
result
=
''
;
for
(
const
[
i
,
elem
]
of
arr
.
entries
())
{
if
(
i
>
0
)
{
result
+=
', '
;
}
result
+=
String
(
elem
);
}
return
result
;
}
此函式使用方式如下
> toString(['eeny', 'meeny', 'miny', 'moe'])
'eeny, meeny, miny, moe'