We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
我们都使用过for...of语句,并大部分时候用在Array上,不仅如此,它还可以迭代String、Set、Map、函数的arguments对象、NodeList对象。
for...of
其实for...of是可以迭代任何可迭代对象(实现了可迭代协议的对象)的,下面将继续讲解。
可迭代协议允许 JavaScript 对象去定义或定制它们的迭代行为, 例如(定义)在一个 for..of 结构中什么值可以被循环(得到)。
实现可迭代协议的对象叫做可迭代对象。
为了变成可迭代对象, 一个对象必须实现 @@iterator 方法,意思是这个对象(或者它原型链 prototype chain 上的某个对象)必须有一个名字是 Symbol.iterator 的属性。
Symbol.iterator 是一个函数,这个函数可以是生成器函数(执行后也会返回符合迭代器协议的对象),或者直接返回符合迭代器协议的对象。
比如String、Array、TypedArray、Map、WeakMap、Set 和 WeakSet 都是是实现了可迭代协议。
这里有一个String相关的例子:
let someString = "hi"; typeof someString[Symbol.iterator]; // "function" let iterator = someString[Symbol.iterator](); // 实现了迭代器协议对象 iterator.next(); // { value: "h", done: false } iterator.next(); // { value: "i", done: false } iterator.next(); // { value: undefined, done: true }
当然我们也可以自定义一个实现了可迭代协议的对象:
// Symbol.iterator 是生成器函数 var myIterable = {}; myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...myIterable]; // [1, 2, 3] // 返回符合**迭代器协议**的对象 var someString = new String("hi"); someString[Symbol.iterator] = function() { return { // 只返回一次元素,字符串 "bye",的迭代器对象 next: function() { if (this._first) { this._first = false; return { value: "bye", done: false }; } else { return { done: true }; } }, _first: true }; }; console.log([...someString]; // ["bye"]
实现了可迭代协议的对象的使用场景:
迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值。
当一个对象被认为是一个迭代器时,它实现了一个 next() 的方法,并且该方法返回的对象里必须包含:
虽然自定义的迭代器是一个有用的工具,但由于需要显式地维护其内部状态,因此需要谨慎地创建。
Generators提供了一个强大的选择:它允许你定义一个包含自有迭代算法的函数, 同时它可以自动维护自己的状态。
如果使用function*语法,则函数将变为GeneratorFunction。
GeneratorFunction 是一个可以作为迭代器工厂的特殊函数。当它被执行时会返回一个新的生成器(iterator)对象。
如前面提到的迭代器协议所说,生成器对象有一个常用的API:next(),它会返回一个对象,value字段包含yield表达式返回的值,done字段表示生成器对象是否已经返回所有值。
next()
value
done
在GeneratorFunction内部,yield关键字可以在每次生成器对象调用next()的时候返回一次值。
yield ..和next(..)这一对组合起来,在生成器的执行过程中构成了一个双向消息传递系统。这也是可以使用生成器函数作为async/await的语法糖的原因。
由于生成器函数返回的生成器对象既是可迭代对象也是迭代器。所以生成器可以被for...of调用,也可以iterator.next().value调用每次的迭代值。
iterator.next().value
for...of语句,每次循环返回的是迭代器对象的value。形式如下:
for (let iterator.next().value of iterable) {}
生成器函数每次被调用返回的也是迭代器对象的value,只不过在函数内部用yield语句来表示迭代器对象的value。
yield
for...of 迭代器和生成器 迭代协议 Generator
The text was updated successfully, but these errors were encountered:
No branches or pull requests
概述
我们都使用过
for...of
语句,并大部分时候用在Array上,不仅如此,它还可以迭代String、Set、Map、函数的arguments对象、NodeList对象。其实
for...of
是可以迭代任何可迭代对象(实现了可迭代协议的对象)的,下面将继续讲解。1. 可迭代协议(The iterable protocol)
可迭代协议允许 JavaScript 对象去定义或定制它们的迭代行为, 例如(定义)在一个 for..of 结构中什么值可以被循环(得到)。
实现可迭代协议的对象叫做可迭代对象。
为了变成可迭代对象, 一个对象必须实现 @@iterator 方法,意思是这个对象(或者它原型链 prototype chain 上的某个对象)必须有一个名字是 Symbol.iterator 的属性。
Symbol.iterator 是一个函数,这个函数可以是生成器函数(执行后也会返回符合迭代器协议的对象),或者直接返回符合迭代器协议的对象。
比如String、Array、TypedArray、Map、WeakMap、Set 和 WeakSet 都是是实现了可迭代协议。
这里有一个String相关的例子:
当然我们也可以自定义一个实现了可迭代协议的对象:
实现了可迭代协议的对象的使用场景:
2. 迭代器协议(The iterator protocol)
迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值。
当一个对象被认为是一个迭代器时,它实现了一个 next() 的方法,并且该方法返回的对象里必须包含:
3. 生成器
虽然自定义的迭代器是一个有用的工具,但由于需要显式地维护其内部状态,因此需要谨慎地创建。
Generators提供了一个强大的选择:它允许你定义一个包含自有迭代算法的函数, 同时它可以自动维护自己的状态。
如果使用function*语法,则函数将变为GeneratorFunction。
GeneratorFunction 是一个可以作为迭代器工厂的特殊函数。当它被执行时会返回一个新的生成器(iterator)对象。
如前面提到的迭代器协议所说,生成器对象有一个常用的API:
next()
,它会返回一个对象,value
字段包含yield表达式返回的值,done
字段表示生成器对象是否已经返回所有值。yield ..和next(..)这一对组合起来,在生成器的执行过程中构成了一个双向消息传递系统。这也是可以使用生成器函数作为async/await的语法糖的原因。
由于生成器函数返回的生成器对象既是可迭代对象也是迭代器。所以生成器可以被
for...of
调用,也可以iterator.next().value
调用每次的迭代值。4. 结语
for...of
语句,每次循环返回的是迭代器对象的value。形式如下:生成器函数每次被调用返回的也是迭代器对象的value,只不过在函数内部用
yield
语句来表示迭代器对象的value。参考
for...of
迭代器和生成器
迭代协议
Generator
The text was updated successfully, but these errors were encountered: