1、ES2017标准引入async函数,那么async函数到底是个什么函数呢?
async 是一个generator函数的语法糖。
2、那么generator函数到底是什么函数ne?
generator函数是ES6提供的一种异步编程解决方案,与传统函数完全不同。
3、如何去理解generator函数呢?
从语法上,可以认为generator函数是一个状态机,封装了多个内部状态。
从返回内容上,可以认为generator函数是一个遍历器对象生成器,执行generator函数会返回一个遍历器对象,可以通过next函数一次遍历内部的每一个状态。
从形式上,generator函数是一个普通函数,有两个特征,(1)function关键字与函数之间有一个*号;(2)函数内部使用yield表达式,定义不同的内部状态(yield)(yield意思是溢出)
4、举个栗子
(1)上述函数,定义一个generator函数helloSuningGenerator,他的内部有两个yield表达式(hello和suning),也就是说,该函数有三个状态:hello,suning,return语句(结束执行)。调用generator函数和普通函数一样,加(),但是generator函数并不执行,返回的是undefined。
(2)调用遍历器对象使用next方法,使指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或者上一次停下来的地方开始执行,遇到下一个yield表达式(或return语句)为止。yield表达式是暂停执行的标记,而next方法可以恢复执行。
上面代码说明一共调用四次next方法。
第一次调用,generator函数开始执行,直到遇到第一个yield表达式为止。next方法返回一个对象,返回对象的value值就是当前yield表达式的值hello。done属性值false,表示遍历还没有结束。
第二次调用,generator函数从上次yield表达式停下来地方,一直执行到下一个yield表达式。next方法返回对象的value属性就是当前yield表达式的值world。done属性值false,表示遍历还没有结束。
第三次调用,generator函数从上次yield表达式停下来的地方,一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value值属性,就是紧跟return与后边的表达式的值。done属性为true,以后调用next方法,done属性都是这个值。
5、总结
调用generator函数,返回一个遍历器对象,代表generator函数内部指针。以后,每一次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。
value属性表示当前内部状态的值,是yield表达式后边那个表达式的值;
done属性是一个布尔值,表示遍历时候结束。
------------------------------------------------
那么yield表达式是什么ne ?
yield表达式
由于generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
遍历器对象的next方法的运行逻辑如下:
(1)遇到yield表达式,就暂停执行后边的操作,并且将紧跟在yield后边的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法,在之前暂停的地方继续往下执行,知道遇到下一个yield表达式。
(3)如果没有遇到新的yield的表达式,就一直运行到函数结束,直到return语句为止,并将return语句后边的表达式的值作为返回对象的value属性值。
(4)如果该函数没有return语句,则返回对象的value属性值为undefined。
注意:
yield表达式后边的表达式,只有当调用next方法,内部指针指向该语句时才会执行。
1、举个栗子
上面代码中,23+78不会立即求值,只有在调用next方法将指针移到这一句时,才会求值。
2、yield表达式和return语句相同点和区别?
相同之处是:都能返回紧跟在语句后边的那个表达式的值,作为返回对象的value属性的值。
不同之处是:(1)每次遇到yield,函数停止执行,下一次再从这个位置继续向后执行;而return语句不具备记忆功能。(2)一个函数中,只能执行一次(或者说一个)return语句,但是可以执行多次(多个)yield表达式,当时generator可以不用yield表达式,这样可以贬称一个暂缓执行的函数。
上面代码中,f 如果是普通函数,在为gene赋值时才会执行。但是generator函数,变成只用调用next方法,函数f才会执行。
3、举个栗子
上面代码,yield必须在generator函数里面,不然会报错。
4、举个栗子
上面代码会产生句法错误,因为forEach方法的参数是一个普通函数,但是在里面使用了yield表达式。
一种修改方法是改用for循环。
上面代码还是显示undefined。
5、举个栗子
报错
上面代码显示,没有定义
上面代码显示,没有定义
6、举个栗子
------------------------------------------------
那么next方法参数
yield表达式本身没有返回值,或者说是undefined。next方法可以带一个参数,该参数会被当成上一个yield表达式的返回值。
上面代码先定义了一可以无限运行的generator函数f ,如果next方法没有参数,每次运行到yield表达式,变量reset的值总是undefined。当带一个参数true,变量reset就被重置为这个参数。
generator函数从暂停状态到恢复状态运行,他的上下文(context)是不变的。通过next方法的参数,就可以实现generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。
举个栗子
上面代码中,第一次运行后,5+1=6;第二次运行next方法不带参数,y的值为2*undefined,除以3还是NAN,因此返回的对象的value值也是NAN。第三次运行next方法不带参数,z也是undefined,返回的对象的value属性等于5+NAN+undefined,即NAN。
紧接着执行
上面代码,第一次调用next方法,返回x+1=6;第二次调用next方法,上一次yield表达式的值设12,因此y=24;返回y/3=8;第三次调用next方法,将上一次yield表达式的值设为13,因此找3,这时候新,于4,所以return语句的值=42。
注意:next方法的参数表示上一个yield表达式的返回值,所以第一次使用next方法时,传递参数是无效的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。