js中Generator函数的深入讲解

前言

Generator函数是es6提供的一种异步编程的解决方案,语法行为与传统函数完全不一样。

Generator函数有多种理解角度,从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。

行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了是状态机还是一个遍历器对象生成函数。 返回遍历器对象,可以依次遍历Generator函数内部的每一个状态。

下面话不多说了,来一起看看详细的介绍吧

语法上

首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

形式上

Generator 函数是一个普通函数,但是有两个特征。

一是,function关键字与函数名之间有一个星号;
 二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。

调用上

Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)。我们必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行

function* helloWorldGenerator() {
 yield 'hello';
 yield 'world';
 return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

yield表达式

yield表达式与return语句既有相似之处,也有区别。相似之处在于,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。正常函数只能返回一个值,因为只能执行一次return;Generator 函数可以返回一系列的值,因为可以有任意多个yield。从另一个角度看,也可以说 Generator 生成了一系列的值,这也就是它的名称的来历(英语中,generator 这个词是“生成器”的意思)。

语法注意点:

1.yield表达式只能用在 Generator 函数里面

2.yield表达式如果用在另一个表达式之中,必须放在圆括号里面

3.yield表达式用作函数参数或放在赋值表达式的右边,可以不加括号。

例如:

function* demo() {
 foo(yield 'a', yield 'b'); // OK
 let input = yield; // OK
}

next 方法的参数

yield表达式本身没有返回值(就是说let a=yield ;会返回undefined),或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值 (注意,是表达式的返回值,例如 let a=yield.......... 参数会是a 的值并且会覆盖表达式之前的值)。

function* f() {
 for(var i = 0; true; i++) {
 var reset = yield i;
 console.log(reset);
 if(reset) { i = -1; }
 }
}

var g = f();

g.next() 

由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。V8 引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。从语义上讲,第一个next方法用来启动遍历器对象,所以不用带有参数。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • 在Node.js中使用Javascript Generators详解

    Generators是Javascript的一种协同程序( coroutine 简称:协程)风格,是指那些可以在执行时暂停然后又恢复的函数,该函数是在functi配以星号符号形式如function* ,函数内有些特征关键词如yield 和yield*. function* generatorFn () { console.log('look ma I was suspended') } var generator = generatorFn() // [1] setTimeout(functio

  • js使用generator函数同步执行ajax任务

    本文实例为大家分享了js使用generator函数同步执行ajax任务的具体代码,供大家参考,具体内容如下 function request(url, callback) { fetch(url, {mode: 'cors', credentials: 'include', headers: new Headers({ 'X-Requested-With': 'XMLHttpRequest' })}) .then(response => response.text()) .then(text =

  • 详解JavaScript ES6中的Generator

    今天讨论的新特性让我非常兴奋,因为这个特性是 ES6 中最神奇的特性. 这里的"神奇"意味着什么呢?对于初学者来说,该特性与以往的 JS 完全不同,甚至有些晦涩难懂.从某种意义上说,它完全改变了这门语言的通常行为,这不是"神奇"是什么呢. 不仅如此,该特性还可以简化程序代码,将复杂的"回调堆栈"改成直线执行的形式. 我是不是铺垫的太多了?下面开始深入介绍,你自己去判断吧. 简介 什么是 Generator? 看下面代码: function* qu

  • 小议JavaScript中Generator和Iterator的使用

    一说到 Generator,大家就会扯上异步之类是话题.这显然是被一些奇奇怪怪的东西带坏了.与 Generator 关系密切的应该是 Iterator 才对,拿 Generator 来处理异步也许是一些 C# 程序员才会想的事.当然这种用法确实有一套完整的东西,只是我个人不喜欢而已. 非要把 Generator 和异步联系上,唯一的点就是 next 的调用时机.因为 next 可以异步地调用,所以 Generator 才得以被异步地滥用. 但我觉得 next 这个方法虽然可以异步调用,但正确的使

  • 浅析JavaScript 箭头函数 generator Date JSON

    ES6 标准新增了一种新的函数: Arrow Function(箭头函数). x => x *x 上面的箭头相当于: function (x){ return x*x; } 箭头函数相当于匿名函数,并且简化了函数定义.一种像上面的,只包含一个表达式, 连{ ... }和return都省略掉了.还有一种可以包含多条语句,这时候就不能省略{ ... }和return: x =>{ if(x > 0){ return x * x; }else{ return -x *x; } } 如果参数不是

  • 深入理解js generator数据类型

    1. 概述 generator 是ES6引入的新的数据类型, 看上去像一个函数,除了使用return返回, yield可以返回多次. generator 由function* 定义, (注意*号), 2. 例子 函数无法保存状态, 有时需要全局变量来保存数字: 2.1 'use strict'; function next_id(){ var id = 1; while(id<100){ yield id; id++; } return id; } // 测试: var x, pass = tr

  • JavaScript 中使用 Generator的方法

    Generator 是一种非常强力的语法,但它的使用并不广泛(参见下图 twitter 上的调查!).为什么这样呢?相比于 async/await,它的使用更复杂,调试起来也不太容易(大多数情况又回到了从前),即使我们可以通过非常简单的方式获得类似体验,但是人们一般会更喜欢 async/await. 然而,Generator 允许我们通过 yield 关键字遍历我们自己的代码!这是一种超级强大的语法,实际上,我们可以操纵执行过程!从不太明显的取消操作开始,让我们先从同步操作开始吧. 我为文中提到

  • JavaScript中 ES6 generator数据类型详解

    1. generator简介 generator 是ES6引入的新的数据类型, 看上去像一个函数,除了使用return返回, yield可以返回多次. generator 由function* 定义, (注意*号), 2. 示例 函数无法保存状态, 有时需要全局变量来保存数字: 2.1 'use strict'; function next_id(){ var id = 1; while(id<100){ yield id; id++; } return id; } // 测试: var x,

  • js中Generator函数的深入讲解

    前言 Generator函数是es6提供的一种异步编程的解决方案,语法行为与传统函数完全不一样. Generator函数有多种理解角度,从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态. 执 行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了是状态机还是一个遍历器对象生成函数. 返回遍历器对象,可以依次遍历Generator函数内部的每一个状态. 下面话不多说了,来一起看看详细的介绍吧 语法上 首先可以把它理解成,Generat

  • 深入理解js 中async 函数的含义和用法

    一.终极解决 异步操作是 JavaScript 编程的麻烦事,麻烦到一直有人提出各种各样的方案,试图解决这个问题. 从最早的回调函数,到 Promise 对象,再到 Generator 函数,每次都有所改进,但又让人觉得不彻底.它们都有额外的复杂性,都需要理解抽象的底层运行机制. 异步I/O不就是读取一个文件吗,干嘛要搞得这么复杂?异步编程的最高境界,就是根本不用关心它是不是异步. async 函数就是隧道尽头的亮光,很多人认为它是异步操作的终极解决方案. 二.async 函数是什么? 一句话,

  • js中匿名函数的创建与调用方法分析

    本文实例分析了js中匿名函数的创建与调用方法.分享给大家供大家参考.具体实现方法如下: 匿名函数就是没有名字的函数了,也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数.最经常用作回调函数(callback)参数的值,很多新手朋友对于匿名函数不了解.这里就来分析一下. function 函数名(参数列表){函数体;} 如果是创建匿名函数,那就应该是: function(){函数体;} 因为是匿名函数,所以一般也不会有参数传给他. 为什么要创建匿名函数呢?在什么情况下会使用到匿

  • js中变量的连续赋值(实例讲解)

    今天遇到了一个连续赋值的经典案例,网友们给出的答案也是五花八门,看起来有些繁琐,我也来说说自己的看法. 下面就是这个经典案例: var a = {n: 1}: var b = a; a.x = a = {n: 2}: console.log(a); console.log(b); console.log(a.x); console.log(b.x): 我们先来看一下普通连续赋值,即:变量赋值的类型是数据类型值 var a=3; var b=a=5; console.log(a); console

  • 对js中回调函数的一些看法

    最近在忙公司android的项目,所以也就很少抽时间来写些东西了.刚闲下来,我就翻了翻之前看的东西.做了android之后更加感觉到手机端开发的重要性,现在做native App  和Web App是主流,也就是说现在各种基于浏览器的web app框架也会越来越火爆了,做js的也越来越有前途.我也决定从后端开发渐渐向前端开发和手机端开发靠拢,废话不说了,我们来切入正题"js的回调函数"相关的东西. 说起回调函数,好多人虽然知道意思,但是还是一知半解.至于怎么用,还是有点糊涂.网上的一些

  • 浅析JS中对函数function的理解(基础篇)

    正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定义方式(见下文)之外,还有一种定义的方式能更直观的体现出这个概念: var sum = new Function("num1", "num2", "return num1 + num2"); //不推荐 Function的构造函数可以接收任意数量的参

  • 关于原生js中bind函数的简单实现

    今天继续研究了bind函数的实现,也知道了shim和polyfill的说法,现在总结一下, if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 internal IsCallable function throw new Typ

  • JS中encodeURIComponent函数用php解码的代码

    JS中encodeURIComponent函数给中文编码后,如何用php解码?? 前提:编码前的中文可能是gbk,gb2312,utf-8等. 复制代码 代码如下: urldecode() iconv() 在JS中使用了encodeURIComponent对中文进行编码在PHP中使用iconv('UTF-8','gb2312',$q);就可以得到你需要的字串了,其中gb2312根据你实际应用来定如还不明白为什么看下面的文章 URL编码转换,escape() encodeURI() encodeU

  • js中eval()函数和trim()去掉字符串左右空格应用

    对于js中eval()函数的理解和写一个函数trim()去掉字符串左右空格. trim()是参照了jquery的源码,你可以放心使用. 对于js中eval()函数的理解是本人心得不一定正确. 复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <he

  • 浅谈js中test()函数在正则中的使用

    test() 方法用于检测一个字符串是否匹配某个模式. 返回一个 Boolean 值,它指出在被查找的字符串中是否匹配给出的正则表达式. regexp.test(str) 参数 regexp 必选项.包含正则表达式模式或可用标志的正则表达式对象. str    必选项.要在其上测试查找的字符串. 说明 test 方法检查字符串是否与给出的正则表达式模式相匹配,如果是则返回 true,否则就返回 false. 每个正则表达式都有一个 lastIndex 属性,用于记录上一次匹配结束的位置. var

随机推荐