ES6 在把 JavaScript 中我们熟悉的 for 和 for..in 循环组合起来的基础上,又新增了一个for..of 循环,在迭代器产生的一系列值上循环。
for..of 循环的值必须是一个 iterable,或者说它必须是可以转换 / 封箱到一个 iterable 对象的值。iterable 就是一个能够产生迭代器供循环使用的对象。
for..of 和 for..in区别,废话不多说上代码:
var a = ["a","b","c","d","e"];
for (var idx in a) {
console.log( idx );
}
// 0 1 2 3 4
for (var val of a) {
console.log( val );
}
// "a" "b" "c" "d" "e"
for...in遍历了数组的键/索引,for-of遍历列值
下面是前面代码中的前 ES6 版本的 for..of 形式:
var a = ["a","b","c","d","e"],
k = Object.keys( a );
for (var val, i = 0; i < k.length; i++) {
val = a[ k[i] ];
console.log( val );
}
// "a" "b" "c" "d" "e"
这里是 ES6 的但是不用 for..of 的等价代码,也可以用来展示如何手动在迭代器上迭代:
var a = ["a","b","c","d","e"];
for (var val, ret, it = a[Symbol.iterator]();
(ret = it.next()) && !ret.done;
) {
val = ret.value;
console.log( val );
}
// "a" "b" "c" "d" "e"
在底层,for..of 循环向 iterable 请求一个迭代器,然后反复调用这个迭代器把它产生的值赋给循环迭代变量。
JavaScript 中默认为(或提供)iterable 的标准内建值包括:Arrays 、 Strings、 Generators、 Collections / TypedArrays ;
注意
默认情况下平凡对象并不适用 for..of 循环。因为它们并没有默认的迭代器,这是有意设计的特性,而不是错误。但是我们可以为对象设置一个迭代器来迭代对象,得到我们定义的值
下面是在原生字符串的字符上迭代的方式:
for (var c of "hello") {
console.log( c );
}
// "h" "e" "l" "l" "o"
原生字符串值 "hello" 被强制类型转换 / 封箱到等价的 String 封装对象中,而这默认是一个 iterable。
在 for (XYZ of ABC).. 中,和 for 以及 for..in 循环中的语句一样,XYZ 语句可以是赋值表达式也可以是声明。所以可以这么做:
var o = {};
for (o.a of [1,2,3]) {
console.log( o.a );
}
// 1 2 3
for ({x: o.a} of [ {x: 1}, {x: 2}, {x: 3} ]) {
console.log( o.a );
}
// 1 2 3
和其他循环一样,for..of 循环也可以通过 break、continue、return(如果在函数中的话)提前终止,并抛出异常。在所有这些情况中,如果需要的话,都会自动调用迭代器的return(..) 函数(如果存在的话)让迭代器执行清理工作。