for...of妙用
refer: 为什么说for...of循环是JS中的宝石
Summary
- 简明扼要
- 它接受迭代器,包括数组,字符串,Set,Map,DOM集合
- 它接受类数组对象
- 迭代的项目可以在就地解构
1. 如何判断数据是否可迭代
查看 Symbol.iterator
方法来确定某个数据是否可迭代。Symbol.iterator
返回一个 iterator
对象。iterator
对象有 next
方法,它会返回一个对象, 对象当中包含value
值和boolean
类型的done
。 例如,下面的例子显示了数组是可迭代的。
const array = [1, 2, 3];
const iterator1 = array[Symbol.iterator]();
iterator1.next(); // => { value: 1, done: false }
2. 数组迭代
const products = ['oranges', 'apples'];
for (const product of products) {
console.log(product);
}
// 'oranges'
// 'apples'
此外,数组方法 entries()
可以用于访问迭代项的索引。该方法在每次迭代时返回一对 [index,item]
。
3. 类数组迭代
function
的输入变量arguments
是函数体内的特殊变量,包含函数的所有参数,这是一个经典的类数组对象。
function sum() {
let sum = 0;
for (const number of arguments) {
sum += number;
}
return sum;
}
sum(1, 2, 3); // => 6
4. JavaScript对象迭代
old way -
const person = {
name: 'John Smith',
job: 'agent'
};
// way one
// forEach
Object.keys(person).forEach(prop => {
console.log(prop, person[prop]);
});
// way two
// for...in + hasOwnProperty
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key, person[key]);
}
}
// 'name', 'John Smith'
// 'job', 'agent'
currently -
const person = {
name: 'John Smith',
job: 'agent'
};
for (const [prop, value] of Object.entries(person)) {
console.log(prop, value);
}
// 'name', 'John Smith'
// 'job', 'agent'
5. Map 和 Set 迭代
Map
是一个特殊的对象,将键与值相关联。键可以是任何基本类型(通常是 string
,但可以是 number
等)。
幸运的是,Map
也是可迭代的(在键/值对上进行迭代),并且 for...of
可以轻松地循环迭代所有键/值对。在每个循环中,迭代器都会返回一个数组 [key,value]
,并使用 const [number,name]
立即对这对数组进行解构。
const names = new Map();
names.set(1, 'one');
names.set(2, 'two');
for (const [key, value] of names) {
console.log(key, name);
}
// logs 1, 'one'
// logs 2, 'two'
7. 遍历DOM集合
每个 DOM
元素的 children
属性都是 HTMLCollection
。好在 for...of
可以在类似数组的对象上进行迭代,因此我们可以轻松地迭代 children
:
const children = document.body.children;
for (const child of children) {
console.log(child); // logs each child of <body>
}
for...of
可以迭代 NodeList
集合(可迭代)。例如,函数 document.querySelectorAll(query)
返回一个 NodeList
:
const allImages = document.querySelectorAll('img');
for (const image of allImages) {
console.log(image); // log each image in the document
}
2.对象解构
for (LeftHandSideExpression of Expression) {
// statements
}
LeftHandSideExpression
表达式可以替换为任意赋值表达式左侧的内容。
const persons = [
{ name: 'John Smith' },
{ name: 'Jane Doe' }
];
for (const { name } of persons) {
console.log(name);
}
// 'John Smith'
// 'Jane Doe'
8. 性能
迭代大型数组时,for...of
的执行速度可能会比经典方法慢:
const a = [/* big array */];
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
}
在每次迭代中调用迭代器比通过增加索引访问的开销更大。但是,这种细微差别在使用大型数组的应用程序中以及性能至关重要的应用程序中非常重要,不过这种情况很少发生。