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 中的 [键,值] 条目(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
与解构结合使用对于 [键,值] 对(编码为数组)的可迭代对象特别有用。这就是 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()
也返回一个 [键,值] 对的可迭代对象
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'