“可迭代对象”,这个词…倒是经常听说

82 阅读2分钟

定义

可迭代对象,必须实现[Symbol.iterator]()方法(要么该对象有这个属性,要么它的原型链上有这个属性)

当一个对象需要被迭代时(比如在一个 for...of 循环中),首先会不带参数调用它的 [Symbol.iterator](),然后使用此方法返回的迭代器获取迭代的值

迭代器是一个拥有 next 方法的对象,返回符合 IteratorResult 接口的对象(包含 value、done 等属性)

WX20240815-173649@2x.png

内置的可迭代对象

  • String
  • Array
  • Map
  • Set
// String
const text = "Hello";
for (const char of text) {
	console.log(char);
}

// Array
const numbers = [1, 2, 3];
for (const number of numbers) {
	console.log(number);
}

// Map
const map = new Map([
	["key1", "value1"],
	["key2", "value2"],
]);
for (const [key, value] of map) {
	console.log(`${key}: ${value}`);
}

// Set
const set = new Set([1, 2, 3, 4, 5]);
for (const value of set) {
	console.log(value);
}

接受可迭代对象的 API

  • Map()
  • WeakMap()
  • Set()
  • WeakSet()
  • Promise.all()
  • Promise.allSettled()
  • Promise.race()
  • Promise.any()
  • Array.from()
// Map()
const entries = [
	["key1", "value1"],
	["key2", "value2"],
];
const map = new Map(entries);
console.log(map.get("key1")); // 输出: value1

// WeakMap()
const key = { name: "WeakMapKey" };
const weakMap = new WeakMap([[key, "value"]]);
console.log(weakMap.get(key)); // 输出: value

// Set()
const items = [1, 2, 3, 3];
const set = new Set(items);
console.log(set.size); // 输出: 3

// WeakSet()
const key1 = { name: "WeakSetKey1" };
const key2 = { name: "WeakSetKey2" };
const weakSet = new WeakSet([key1, key2]);
console.log(weakSet.has(key1)); // true

// Promise.all()
Promise.all([Promise.resolve(1), Promise.resolve(2)]).then((values) =>
	console.log(values)
); // 输出: [1, 2]

// Promise.allSettled()
Promise.allSettled([Promise.resolve(1), Promise.reject(2)]).then((results) =>
	console.log(results)
);
// 输出: [{status: "fulfilled", value: 1}, {status: "rejected", reason: 2}]

// Promise.race()
Promise.race([
	Promise.resolve("First"),
	new Promise((resolve) => setTimeout(() => resolve("Second"), 1000)),
]).then((value) => console.log(value)); // 输出: First

// Promise.any()
Promise.any([Promise.reject("First"), Promise.resolve("Second")]).then(
	(value) => console.log(value)
); // 输出: Second

// Array.from()
const map = new Map([
	[1, "one"],
	[2, "two"],
]);
const array = Array.from(map);
console.log(array); // 输出: [[1, 'one'], [2, 'two']]

一些期望可迭代对象的语句和表达式

  • for...of 循环
  • 数组和参数的扩展
  • yield*
  • 数组解构
// for...of
const iterableArray = [1, 2, 3, 4];
for (const value of iterableArray) {
	console.log(value);
}
// 输出:
// 1
// 2
// 3
// 4

// 扩展
function sum(x, y, z) {
	return x + y + z;
}
const numbers = [1, 2, 3];
const result = sum(...numbers); // 相当于调用 sum(1, 2, 3)
console.log(result); // 输出: 6

// yield
function* generatorOne() {
	yield 1;
	yield 2;
	yield* [3, 4, 5]; // 委派给数组
	yield 6;
}

const genOne = generatorOne();
console.log(genOne.next().value); // 1
console.log(genOne.next().value); // 2
console.log(genOne.next().value); // 3
console.log(genOne.next().value); // 4
console.log(genOne.next().value); // 5
console.log(genOne.next().value); // 6

// 解构
const [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // 2
console.log(rest); // [3, 4, 5]

示例

string 的 [Symbol.iterator] 方法
const someString = "Hello World";
const iterator = someString[Symbol.iterator]();

console.log(iterator.next()); // { value: 'H', done: false }
console.log(iterator.next()); // { value: 'e', done: false }
console.log(iterator.next()); // { value: 'l', done: false }
自定义可迭代对象
const myIterable = {
	*[Symbol.iterator]() {
		yield 1;
		yield 2;
		yield 3;
	},
};

console.log([...myIterable]); // [1, 2, 3]