mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 10:22:23 +00:00
edit docs/iterator & generator
This commit is contained in:
parent
3a4f714af5
commit
ad0499d0e4
@ -60,6 +60,8 @@ Generator函数使用iterator接口,每次调用next方法的返回值,就
|
||||
|
||||
Generator函数的本质,其实是提供一种可以暂停执行的函数。yield语句就是暂停标志,next方法遇到yield,就会暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回对象的value属性的值。当下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句。如果没有再遇到新的yield语句,就一直运行到函数结束,将return语句后面的表达式的值,作为value属性的值,如果该函数没有return语句,则value属性的值为undefined。
|
||||
|
||||
由于yield后面的表达式,直到调用next方法时才会执行,因此等于为JavaScript提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。
|
||||
|
||||
yield语句与return语句有点像,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。
|
||||
|
||||
Generator函数可以不用yield语句,这时就变成了一个单纯的暂缓执行函数。
|
||||
@ -125,6 +127,35 @@ loadUI.next()
|
||||
|
||||
上面代码表示,第一次调用loadUI函数时,该函数不会执行,仅返回一个遍历器。下一次对该遍历器调用next方法,则会显示Loading界面,并且异步加载数据。再一次使用next方法,则会隐藏Loading界面。可以看到,这种写法的好处是所有Loading界面的逻辑,都被封装在一个函数,按部就班非常清晰。
|
||||
|
||||
总结一下,如果某个操作非常耗时,可以把它拆成N步。
|
||||
|
||||
```javascript
|
||||
|
||||
function* longRunningTask() {
|
||||
yield step1();
|
||||
yield step2();
|
||||
// ...
|
||||
yield stepN();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
然后,使用一个函数,按次序自动执行所有步骤。
|
||||
|
||||
```javascript
|
||||
|
||||
scheduler(longRunningTask());
|
||||
|
||||
function scheduler(task) {
|
||||
setTimeout(function () {
|
||||
if (!task.next().done) {
|
||||
scheduler(task);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
注意,yield语句是同步运行,不是异步运行(否则就失去了取代回调函数的设计目的了)。实际操作中,一般让yield语句返回Promises对象。
|
||||
|
||||
```javascript
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
遍历器(Iterator)是一种协议,任何对象只要部署这个协议,就可以完成遍历操作。在ES6中,遍历操作特指for...of循环。
|
||||
|
||||
它的作用主要有两个,一是为遍历对象的属性提供统一的接口,二是为使得对象的属性能够按次序排列。
|
||||
|
||||
ES6的遍历器协议规定,部署了next方法的对象,就具备了遍历器功能。next方法必须返回一个包含value和done两个属性的对象。其中,value属性是当前遍历位置的值,done属性是一个布尔值,表示遍历是否结束。
|
||||
|
||||
```javascript
|
||||
@ -52,7 +54,9 @@ it.next().value // '2'
|
||||
|
||||
```
|
||||
|
||||
一个对象只要具备了next方法,就可以用for...of循环遍历它的值。
|
||||
## for...of循环
|
||||
|
||||
ES6中,一个对象只要部署了next方法,就被视为具有iterator接口,就可以用for...of循环遍历它的值。下面用上一节的idMaker函数生成的it遍历器作为例子。
|
||||
|
||||
```javascript
|
||||
|
||||
@ -61,12 +65,18 @@ for (var n of it) {
|
||||
break;
|
||||
console.log(n);
|
||||
}
|
||||
// 0
|
||||
// 1
|
||||
// 2
|
||||
// 3
|
||||
// 4
|
||||
// 5
|
||||
|
||||
```
|
||||
|
||||
## for...of循环
|
||||
上面代码说明,for...of默认从0开始循环。
|
||||
|
||||
ES6中,任何具备了iterator接口的对象,都可以用for...of循环遍历。数组原生具备iterator接口。
|
||||
数组原生具备iterator接口。
|
||||
|
||||
```javascript
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
- Steven Sanderson, [Experiments with Koa and JavaScript Generators](http://blog.stevensanderson.com/2013/12/21/experiments-with-koa-and-javascript-generators/)
|
||||
- jmar777, [What's the Big Deal with Generators?](http://devsmash.com/blog/whats-the-big-deal-with-generators)
|
||||
- Marc Harter, [Generators in Node.js: Common Misconceptions and Three Good Use Cases](http://strongloop.com/strongblog/how-to-generators-node-js-yield-use-cases/): 讨论Generator函数的作用
|
||||
- Axel Rauschmayer, [Iterators and generators in ECMAScript 6](http://www.2ality.com/2013/06/iterators-generators.html): 探讨Iterator和Generator的设计目的
|
||||
|
||||
## Promise对象
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user