tips:文章主要讲for...of
的使用,穿插对比for..in
的使用
for of 的使用我们可以追溯到Iterator
Iterator接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for…of循环。当使用for…of循环遍历某种数据结构时,该循环会自动去寻找Iterator 接口。
概括:有Iterator 接口的数据结构,就可以使用for…of循环;
原生具备 Iterator 接口的数据结构如下。
const arr = ['red', 'green', 'blue'];
for(let v of arr) {
console.log(v); // red green blue
}
for...in
vs for...of
for…in循环读取键名,for…of循环读取键值;
for…in循环有几个缺点。
- 数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。
- for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
- 某些情况下,for…in循环会以任意顺序遍历键名。
总之,for…in循环主要是为遍历对象而设计的,不适用于遍历数组
for…of循环相比上面几种做法,有一些显著的优点。
- 有着同for…in一样的简洁语法,但是没有for…in那些缺点。
- 不同于forEach方法,它可以与break、continue和return配合使用。
- 提供了遍历所有数据结构的统一操作接口。
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
console.log(e);
}
// Gecko
// Trident
// Webkit
var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262
类似数组的对象包括好几类。下面是for…of循环用于字符串、DOM NodeList 对象、arguments对象的例子。
// 字符串
let str = "hello";
for (let s of str) {
console.log(s); // h e l l o
}
// DOM NodeList对象
let paras = document.querySelectorAll("p");
for (let p of paras) {
p.classList.add("test");
}
// arguments对象
function printArgs() {
for (let x of arguments) {
console.log(x);
}
}
printArgs('a', 'b');
// 'a'
// 'b'
对于普通的对象,for…of结构不能直接使用,会报错。可以使用for…in循环来遍历键名;
所以对象遍历的方法为;
1、for…in循环遍历键名
2、Object.keys方法将对象的键名生成一个数组,然后遍历这个数组
let es6 = {
edition: 6,
committee: "TC39",
standard: "ECMA-262"
};
for (let e in es6) {
console.log(e);
}
// edition
// committee
// standard
for (var key of Object.keys(es6 )) {
console.log(key + ': ' + es6 [key]);
}
有些数据结构是在现有数据结构的基础上,计算生成的。
比如,ES6 的数组、Set、Map 都部署了以下三个方法,调用后都返回遍历器对象。
entries()
返回一个遍历器对象,用来遍历[键名, 键值]组成的数组。
keys()
返回一个遍历器对象,用来遍历所有的键名。values()
返回一个遍历器对象,用来遍历所有的键值。let arr = ['a', 'b', 'c'];
for (let pair of arr.entries()) {
console.log(pair);
}
// [0, 'a']
// [1, 'b']
// [2, 'c']