0%

Javascript for ... of

for … of 功能

javascript中的for ... of语句用来遍历可迭代对象,比如遍历数组可以使用如下代码:

1
2
3
4
5
const nums = [1, 2, 3, 4, 5];
for (const num of nums) {
console.log(num);
}

可迭代对象有很多,包括以下这些:

  1. Array
  2. String
  3. TypeArray
  4. Map
  5. Set
  6. NodeList(and other DOM collections)
  7. Array like objects(arguments)
  8. generators produced by generator functions
  9. User-defined iterables.

for … of 执行原理

for ... of首先会调用可迭代对象的@@iterator()方法获取一个iterator,然后反复调用这个iteratornext方法来获取对应的值。

for … of 何时结束迭代?

以下三种情况都会导致for … of结束迭代。

  1. 遇到break语句
  2. 遇到continue语句
  3. iteratornext方法返回 done: true时(也就是正常遍历结束)

for … of 不会修改被迭代的对象

for … of底层使用generator实现,每次迭代都会生成一个新的变量,所以不会改变被迭代的对象。下面的代码将数组中每个值加1,并不会改变原来的数组,因为变量num时迭代时生成的,而且每次迭代就重新生成一个。

1
2
3
4
5
6
7
const nums = [1, 2, 3];
for (let num of nums) {
num += 1;
console.log(num); // 2, 3, 4
}
console.log(nums); // still [1, 2, 3]

for … of 中可以使用destruction

1
2
3
4
5
6
7
8
9
10
const students = [
{ name: 'Alice', age: 20 },
{ name: 'Bob', age: 21 },
{ name: 'Cindy', age: 22 },
];

for (const { name, age } of students) {
console.log(name, age);
}

何时使用经典的for循环?

所谓经典for循环就是使用下标遍历的循环,类似C语言中的for循环。

1
2
3
4
const nums = [1, 2, 3];
for (let i = 0; i < nums.length; i++) {
console.log(nums[i]);
}

是否使用经典的for循环有一个简单的判断标准,在遍历的过程中是否要改变原数组,如果需要,就使用,否则就可以使用其他循环代替,比如for … of, forEach, filter, map, reduce等。

for…of vs for…in

for ... offor ... in都是用来遍历对象的,但是有一些区别:

  1. for ... of遍历的是可迭代对象,而for ... in遍历的是可枚举对象。
  2. for ... of遍历的是值,而for ... in遍历的是键。

Array

对于数组来说,for ... of遍历的是数组的值,而for ... in遍历的是数组的键(下标)。

1
2
3
4
5
6
7
8
9
10
const nums = [1, 2, 3];
nums.foo = 'bar';

for (const num of nums) {
console.log(num); // 1, 2, 3
}

for (const key in nums) {
console.log(key); // 0, 1, 2, foo
}

Object

在对象上使用for ... of会报错,因为对象不是可迭代对象,但是可以使用for ... in来遍历对象的键。

1
2
3
4
5
6
7
8
9
10
11
12
const obj = {
foo: "bar",
baz: "qux",
};

for (const value of obj) {
console.log(num); // TypeError: obj is not iterable
}

for (const key in obj) {
console.log(key); // 0, 1, 2, foo
}

使用for...of可以对Object.keys或者Object.values来进行遍历。

1
2
3
4
5
6
7
8
9
10
11
12
const obj = {
foo: "bar",
baz: "qux",
};

for (const key of Object.keys(obj)) {
console.log(key); // foo, baz
}

for (const value of Object.values(obj)) {
console.log(value); // bar, qux
}