mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-28 21:32:20 +00:00
修改Readme和generator
This commit is contained in:
parent
38adc8e8eb
commit
2556bf8962
@ -8,7 +8,7 @@
|
||||
|
||||
本书为中级难度,适合已有一定JavaScript语言基础的读者,用来了解这门语言的最新发展;也可当作参考手册,查寻新增的语法点。
|
||||
|
||||
全书已由电子工业出版社出版([版权页](images/copyright.png),[内页1](images/page1.png),[内页2](images/page2.png)),铜版纸全彩印刷,附有索引。电子版与纸版的内容是一致的,如果您对本书感兴趣,建议考虑购买纸版。这样可以使出版社不因出版开源书籍而亏钱,进而鼓励更多的作者开源自己的书籍。
|
||||
全书已由电子工业出版社出版([版权页](images/copyright.png),[内页1](images/page1.png),[内页2](images/page2.png)),铜版纸全彩印刷,附有索引。纸版是根据电子版排印的,内容截止到2014年10月,感谢张春雨编辑支持我将全书开源的做法。如果您对本书感兴趣,建议考虑购买纸版。这样可以使出版社不因出版开源书籍而亏钱,进而鼓励更多的作者开源自己的书籍。
|
||||
|
||||
- [京东](http://item.jd.com/11526272.html)
|
||||
- [当当](http://product.dangdang.com/23546442.html)
|
||||
|
@ -1,6 +1,8 @@
|
||||
# Generator 函数
|
||||
|
||||
## 含义
|
||||
## 语法
|
||||
|
||||
### 简介
|
||||
|
||||
所谓Generator,有多种理解角度。首先,可以把它理解成一个内部状态的遍历器,每调用一次,内部状态发生一次改变(可以理解成发生某些事件)。ES6引入Generator函数,作用就是可以完全控制内部状态的变化,依次遍历这些状态。
|
||||
|
||||
@ -72,7 +74,7 @@ setTimeout(function () {
|
||||
|
||||
上面代码中,函数f如果是普通函数,在为变量generator赋值时就会执行。但是,函数f是一个Generator函数,就变成只有调用next方法时,函数f才会执行。
|
||||
|
||||
## next方法的参数
|
||||
### next方法的参数
|
||||
|
||||
yield语句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
|
||||
|
||||
@ -120,7 +122,7 @@ it.next(13)
|
||||
|
||||
注意,由于next方法的参数表示上一个yield语句的返回值,所以第一次使用next方法时,不能带有参数。V8引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。
|
||||
|
||||
## for...of循环
|
||||
### for...of循环
|
||||
|
||||
for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法。
|
||||
|
||||
@ -165,7 +167,7 @@ for (let n of fibonacci()) {
|
||||
|
||||
从上面代码可见,使用for...of语句时不需要使用next方法。
|
||||
|
||||
## throw方法
|
||||
### throw方法
|
||||
|
||||
Generator函数还有一个特点,它可以在函数体外抛出错误,然后在函数体内捕获。
|
||||
|
||||
@ -245,7 +247,7 @@ function* g(){
|
||||
|
||||
```
|
||||
|
||||
## yield*语句
|
||||
### yield*语句
|
||||
|
||||
如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。
|
||||
|
||||
@ -357,7 +359,7 @@ result
|
||||
|
||||
```
|
||||
|
||||
## 作为对象属性的Generator函数
|
||||
### 作为对象属性的Generator函数
|
||||
|
||||
如果一个对象的属性是Generator函数,可以简写成下面的形式。
|
||||
|
||||
@ -383,7 +385,9 @@ let obj = {
|
||||
|
||||
```
|
||||
|
||||
## Generator与状态机
|
||||
## 含义
|
||||
|
||||
### Generator与状态机
|
||||
|
||||
Generator是实现状态机的最佳结构。比如,下面的clock函数就是一个状态机。
|
||||
|
||||
@ -417,6 +421,16 @@ var clock = function*(_) {
|
||||
|
||||
上面的Generator实现与ES5实现对比,可以看到少了用来保存状态的外部变量ticking,这样就更简洁,更安全(状态不会被非法篡改)、更符合函数式编程的思想,在写法上也更优雅。Generator之所以可以不用外部变量保存状态,是因为它本身就包含了一个状态信息,即目前是否处于暂停态。
|
||||
|
||||
### Generator与协程
|
||||
|
||||
协程(coroutine)是一种程序运行的方式。传统的“子例程”(subroutine)采用堆栈式“后进先出”的执行方式,只有当调用的子函数完全执行完毕,才会结束执行父函数。协程与其不同,多个函数可以并行执行,但是只有一个函数处于正在运行的状态,其他函数都处于暂停态(suspended),函数之间可以交换执行权。也就是说,一个函数执行到一半,可以暂停执行,将执行权交给另一个函数,等到稍后收回执行权的时候,再恢复执行。这种可以并行执行、交换执行权的函数,就称为协程。
|
||||
|
||||
不难看出,协程适合用于多任务运行的环境。在这个意义上,它与线程很相似,都有自己的执行上下文、可以分享全局变量。它们的不同之处在于,同一时间可以有多个线程处于运行状态,但是运行的协程只能有一个,其他都处于暂停状态。此外,线程是抢先式的,到底哪个线程优先得到资源,必须由运行环境决定,但是协程是合作式的,执行权由协程自己分配。
|
||||
|
||||
Generator函数是ECMAScript 6对协程的实现,但属于不完全实现,只做到了暂停执行和转移执行权,有一些特性没有实现,比如不支持所调用的函数之中的yield语句。
|
||||
|
||||
如果将Generator函数看作多任务运行的方式,存在多个进入点和退出点。那么,一方面,并发的多任务可以写成多个Generator函数;另一方面,继发的任务则可以按照发生顺序,写在一个Generator函数之中,然后用一个任务管理函数执行(参考本节的“控制流管理”部分)。
|
||||
|
||||
## 应用
|
||||
|
||||
Generator可以暂停函数执行,返回任意表达式的值。这种特点使得Generator有多种应用场景。
|
||||
@ -661,12 +675,3 @@ function doStuff() {
|
||||
|
||||
上面的函数,可以用一模一样的for...of循环处理!两相一比较,就不难看出Generator使得数据或者操作,具备了类似数组的接口。
|
||||
|
||||
## Generator与协程
|
||||
|
||||
协程(coroutine)是一种程序运行的方式。传统的“子例程”(subroutine)采用堆栈式“后进先出”的执行方式,只有当调用的子函数完全执行完毕,才会结束执行父函数。协程与其不同,多个函数可以并行执行,但是只有一个函数处于正在运行的状态,其他函数都处于暂停态(suspended),函数之间可以交换执行权。也就是说,一个函数执行到一半,可以暂停执行,将执行权交给另一个函数,等到稍后收回执行权的时候,再恢复执行。这种可以并行执行、交换执行权的函数,就称为协程。
|
||||
|
||||
不难看出,协程适合用于多任务运行的环境。在这个意义上,它与线程很相似,都有自己的执行上下文、可以分享全局变量。它们的不同之处在于,同一时间可以有多个线程处于运行状态,但是运行的协程只能有一个,其他都处于暂停状态。此外,线程是抢先式的,到底哪个线程优先得到资源,必须由运行环境决定,但是协程是合作式的,执行权由协程自己分配。
|
||||
|
||||
Generator函数是ECMAScript 6对协程的实现,但属于不完全实现,只做到了暂停执行和转移执行权,有一些特性没有实现,比如不支持所调用的函数之中的yield语句。
|
||||
|
||||
如果将Generator函数看作多任务运行的方式,存在多个进入点和退出点。那么,一方面,并发的多任务可以写成多个Generator函数;另一方面,继发的任务则可以按照发生顺序,写在一个Generator函数之中,然后用一个任务管理函数执行(参考本节的“控制流管理”部分)。
|
||||
|
Loading…
x
Reference in New Issue
Block a user