为什么说for...of循环是JS中的宝石?

简介: 是什么使得一个编程语言的新特性很棒?当这个特性可以结合多个其它特性的时候。ES2015 版本中引入的 for...of 语句就是这种情况。for...of 可以迭代数组、类数组以及任何可以迭代的对象(maps、sets、DOM集合),并且,for...of 的语句还很短。在这篇文章中,我将会演示 for...of 的能力。1. 数组迭代for...of 最常见的应用是对数组项进行迭代。该循环可以高效得完成迭代,而无需其他变量来保持索引。例如:

是什么使得一个编程语言的新特性很棒?当这个特性可以结合多个其它特性的时候。

ES2015 版本中引入的 for...of 语句就是这种情况。

for...of 可以迭代数组、类数组以及任何可以迭代的对象(maps、sets、DOM集合),并且,for...of 的语句还很短。

在这篇文章中,我将会演示 for...of 的能力。

  1. 数组迭代

for...of 最常见的应用是对数组项进行迭代。该循环可以高效得完成迭代,而无需其他变量来保持索引。

例如:

const products = ['oranges', 'apples'];

for (const product of products) {
console.log(product);
}
// 'oranges'
// 'apples'
for...of 循环遍历 products 的每一项。迭代项被赋值给变量 product.

数组方法 entries() 可以用于访问迭代项的索引。该方法在每次迭代时返回一对 [index,item]。

就地解构是 for...of 的另一个重要功能,我们将在下一部分中对其进行详细说明。

1.1 就地解构
首先,我们来看一下 for...of 循环的语法:

for (LeftHandSideExpression of Expression) {
// statements
}
LeftHandSideExpression 表达式可以替换为任意赋值表达式左侧的内容。

在前面的示例中,LeftHandSideExpression 是一个变量声明 const product ,甚至是一个解构 const [index,product]。

因此,for...of 的语法支持实现迭代项的解构。

让我们遍历一个对象数组,提取每个对象的 name 属性:

const persons = [
{ name: 'John Smith' },
{ name: 'Jane Doe' }
];

for (const { name } of persons) {
console.log(name);
}
// 'John Smith'
// 'Jane Doe'
const { name } of persons 循环迭代 persons 对象数组,并且就地将 person 对象进行了解构。

  1. 类数组迭代

for...of 可以用于迭代类数组对象。arguments 是函数体内的特殊变量,包含函数的所有参数,这是一个经典的类数组对象。

让我们写一个求和函数 sum(num1, num2, ..., numN):

function sum() {
let sum = ;
for (const number of arguments) {

sum += number;

}
return sum;
}

sum(1, 2, 3); // => 6
在每次迭代中,for...of 循环遍历类数组 arguments 中的每一个数,并计算总和。

  1. 快速了解可迭代

什么是可迭代对象?它是支持可迭代协议的对象。

我们可以通过查看 Symbol.iterator 方法来确定某个数据是否可迭代。例如,下面的例子显示了数组是可迭代的:

const array = [1, 2, 3];
const iterator1 = array[Symbol.iterator]();
iterator1.next(); // => { value: 1, done: false }
如果你想了解更多信息,可以随时阅读我之前的文章。

for...of 接受可迭代对象。这很棒,因为现在你可以遍历string、数组、类数组、set、map,同时卖QQ号平台仍可以享受 for...of 的简洁。

  1. 字符串迭代

JavaScript 的基础类型 string 是可迭代的。因此,可以轻松地遍历字符串的字符。

const message = 'hello';

for (const character of message) {
console.log(character);
}
// 'h'
// 'e'
// 'l'
// 'l'
// 'o'
message 是一个字符串。由于字符串可迭代的,因此 for...of 循环遍历 message 。

  1. Map 和 Set 迭代

Map 是一个特殊的对象,将键与值相关联。键可以是任何基本类型(通常是 string,但可以是 number 等)。

幸运的是,Map 也是可迭代的(在键/值对上进行迭代),并且 for...of 可以轻松地循环迭代所有键/值对。

一起看一下:

const names = new Map();
names.set(1, 'one');
names.set(2, 'two');

for (const [number, name] of names) {
console.log(number, name);
}
// logs 1, 'one'
// logs 2, 'two'
for (const [number, name] of names) 迭代 names 的键值对。

在每个循环中,迭代器都会返回一个数组 [key,value] ,并使用 const [number,name] 立即对这对数组进行解构。

以相同的方式可以遍历 Set 的项:

const colors = new Set(['white', 'blue', 'red', 'white']);

for (color of colors) {
console.log(color);
}
// 'white'
// 'blue'
// 'red'

  1. 迭代普通的JavaScript对象

尝试遍历普通JS对象的属性/值总是很痛苦。过去,我通常使用 Object.keys() 获取对象的键,然后使用 forEach 来迭代键数组。【译者:这不代表本人观点,我比较喜欢用 for...in 遍历对象,不过要注意 for...in 的副作用】

const person = {
name: 'John Smith',
job: 'agent'
};

Object.keys(person).forEach(prop => {
console.log(prop, person[prop]);
});
// 'name', 'John Smith'
// 'job', 'agent'
新的 Object.entries() 函数与 for...of 组合使用是个不错的选择:

const person = {
name: 'John Smith',
job: 'agent'
};

for (const [prop, value] of Object.entries(person)) {
console.log(prop, value);
}
// 'name', 'John Smith'
// 'job', 'agent'
Object.entries(person) 返回一个键和值的元组数组:[[''name','John Smith'],['job','agent']]。然后,使用 for...of 循环遍历数组,并将每个元组解构为 const [prop,value]。

  1. 遍历DOM集合

你可能知道 HTMLCollection 令人沮丧。主要是因为 HTMLCollection 是一个类数组的对象(而不是常规数组),所以我们无法使用数组的方法。

例如,每个 DOM 元素的 children 属性都是 HTMLCollection 。好在 for...of 可以在类似数组的对象上进行迭代,因此我们可以轻松地迭代 children:

const children = document.body.children;

for (const child of children) {
console.log(child); // logs each child of


}
此外,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
}
如果你想遍历 DOM 中的不同种类的集合,那么 for...of 语句是一个不错的选择。

  1. 性能

迭代大型数组时,for...of 的执行速度可能会比经典方法慢:

const a = [/ big array /];
for (let i = ; i < a.length; i++) {
console.log(a[i]);
}
在每次迭代中调用迭代器比通过增加索引访问的开销更大。但是,这种细微差别在使用大型数组的应用程序中以及性能至关重要的应用程序中非常重要,不过这种情况很少发生。

  1. 总结

为什么说 for...of 是一颗宝石,因为:

它简明扼要

它接受迭代器,包括数组,字符串,Set,Map,DOM集合

它接受类数组对象

迭代的项目可以在就地解构。

你首选的迭代数组项的方式是什么?

目录
相关文章
|
20天前
|
JavaScript
在循环内错误使用函数定义(js的问题)
在循环内错误使用函数定义(js的问题)
11 0
|
21天前
|
JavaScript
JS使用循环求100内奇数之和
JS使用循环求100内奇数之和
16 1
|
1天前
|
JavaScript 索引
JS 几种循环遍历
JS 几种循环遍历
5 0
JS 几种循环遍历
|
28天前
|
开发框架 JavaScript 前端开发
描述JavaScript事件循环机制,并举例说明在游戏循环更新中的应用。
JavaScript的事件循环机制是单线程处理异步操作的关键,由调用栈、事件队列和Web APIs构成。调用栈执行函数,遇到异步操作时交给Web APIs,完成后回调函数进入事件队列。当调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中常用框架提供更高级别的抽象。
11 1
|
1月前
|
JavaScript 前端开发 API
JavaScript循环遍历常用的7种方法以及常用的数组 API
JavaScript循环遍历常用的7种方法以及常用的数组 API
35 0
|
1月前
|
JavaScript
js循环的几种方法
js循环的几种方法
15 2
|
1月前
|
JavaScript 前端开发
javascript中的循环
javascript中的循环
|
2月前
|
存储 缓存 JavaScript
解密迭代艺术:精通JavaScript中的for循环技巧
解密迭代艺术:精通JavaScript中的for循环技巧
27 0
|
3月前
|
前端开发 JavaScript 索引
【面试题】JavaScript高级循环方法
【面试题】JavaScript高级循环方法
|
3月前
|
存储 JavaScript 前端开发
js中 for、forEach、for...in、for...of循环的区别和使用
js中 for、forEach、for...in、for...of循环的区别和使用