摘要:返回的遍历器对象,可以依次遍历函数内部的每一个状态。下一步,必须调用遍历器对象的方法,使得指针移向下一个状态。从语义上讲,第一个方法用来启动遍历器对象,所以不用带有参数。
Generator理解
Generator 函数是 ES6 提供的一种异步编程解决方案,可以这么理解:
从语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
function* helloWorldGenerator() { yield "hello"; yield "world"; return "ending"; } var hw = helloWorldGenerator();
Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)。
下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
hw.next() // { value: "hello", done: false } hw.next() // { value: "world", done: false } hw.next() // { value: "ending", done: true } hw.next() // { value: undefined, done: true }
上面的程序执行了四次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语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。
第四次调用,此时 Generator 函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true。以后再调用next方法,返回的都是这个值。
yield认识由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句或者执行完return之后再运行next的时候,则返回的对象的value属性值为undefined,done为true。
需要注意,yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
yield表达式如果用在另一个表达式之中,必须放在圆括号里面
yield表达式用作函数参数或放在赋值表达式的右边,可以不加括号。
yield放在表达式中的时候,let s =(yield 1+2),s其值将会是undefined,而1+2这个等于3的值将会作为next返回对象的value的值
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
这个参数就是解决了上面说的注意事项的最后一个,yield的返回值总是undefined,
由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。V8 引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。从语义上讲,第一个next方法用来启动遍历器对象,所以不用带有参数。
yield* 表达式如果在 Generator 函数内部,调用另一个 Generator 函数,默认情况下是没有效果的。
这个就需要用到yield*表达式,用来在一个 Generator 函数里面执行另一个 Generator 函数。
function* inner() { yield "hello!"; } function* outer1() { yield "open"; yield inner(); yield "close"; } var gen = outer1() gen.next().value // "open" gen.next().value // 返回一个遍历器对象 gen.next().value // "close" function* outer2() { yield "open" yield* inner() yield "close" } var gen = outer2() gen.next().value // "open" gen.next().value // "hello!" gen.next().value // "close"
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/88924.html
摘要:是处理异步编程的一种方式,来看看和有什么不同或获取值再来看看函数,函数前面是一个然后是函数名,函数体里面是用代表但是可以返回多次使用即不处理后面的返回的是一个对象的写法更像是同步的语句,比更简洁获取值的几种方式调用可以使用获取值表示为最后一 Generator 是es6处理异步编程的一种方式,来看看和promise有什么不同 const myFirstPromise = new Pro...
摘要:调用栈被清空,消息队列中并无任务,线程停止,事件循环结束。不确定的时间点请求返回,将设定好的回调函数放入消息队列。调用栈执行完毕执行消息队列任务。请求并发回调函数执行顺序无法确定。 异步编程 JavaScript中异步编程问题可以说是基础中的重点,也是比较难理解的地方。首先要弄懂的是什么叫异步? 我们的代码在执行的时候是从上到下按顺序执行,一段代码执行了之后才会执行下一段代码,这种方式...
摘要:异步过程控制了解异步的意义之后,我们来对比目前主流几种异步过程控制方法,探讨一下异步编程的最佳实践。结语希望本文对大家有点帮助,能更深刻的理解异步编程,能写出更优雅更高效的代码。 同步和异步(Synchronous and Asynchronous) 了解javascript的同学想必对同步和异步的概念应该都很熟悉了,如果还有不熟悉的同学,我这里举个形象的例子,比如我们早上起床后要干三...
摘要:调用函数后和普通函数不同的是,该函数并不立即执行,也不返回函数执行结果,而是返回一个指向内部状态的对象,也可以看作是一个遍历器对象。第一个只是用来启动函数内部的遍历器,传参也没有多大意义。 之前断断续续接触到了一些ES6的知识,异步编程方面听得比较多的就是Promise,直到最近比较系统地学习了ES6的新特性才发现Generator这个神奇的存在,它可以实现一些前所未有的事情,让我顿时...
摘要:序在中,大家讨论的最多的就是异步编程的操作,如何避免回调的多次嵌套。今天所讲的和就是和异步编程有关,可以帮助我们把异步编程同步化。然而这样的方法依然需要依赖外在的库函数,于是中提出了和关键字。 序 在Javascript中,大家讨论的最多的就是异步编程的操作,如何避免回调的多次嵌套。异步操作的回调一旦嵌套很多,不仅代码会变的臃肿,还很容易出错。各种各样的异步编程解决方案也被不断提出,例...
阅读 2928·2021-11-23 09:51
阅读 3748·2021-11-22 15:29
阅读 3210·2021-10-08 10:05
阅读 1533·2021-09-22 15:20
阅读 921·2019-08-30 15:56
阅读 1029·2019-08-30 15:54
阅读 714·2019-08-26 11:54
阅读 2617·2019-08-26 11:32