Generator函数

基本概念

英文意思为 “生成器”。

  • generator函数是es6提供的一种异步编程解决方案,语法行为与传统函数完全不同。从状态上,首先我们把他理解成一种状态机,封装了多个内部状态。另外执行generator函数胡返回一个遍历对象,就是说,generator函数还是一个遍历器对象生成函数,可以一次遍历函数中的每一个状态。

  • generator函数的两个特征

  1. function命令与函数名之间有一个星号;
  2. 函数体内部使用yield语句定义不同的内部状态(yield为“产出”的意思)。

调用generator函数后,该函数并不执行,返回的也不是函数的运行结果,而是一个指向内部状态的指针对象,也就相当于遍历器对象。下一步必须调用遍历器对象的next方法,使得指针移向下一个状态。就是说每次调用next方法,内部指针就从函数头部或上次停留的地方开始执行,直到遇到吓一跳yield语句或是return语句时停止。yield语句是generator函数的暂停执行,next是恢复执行。

yield语句

是generator函数的暂停标志。

  • next方法的运行逻辑:
  1. 遇到yield语句就暂停执行后面的操作,并将紧跟在yield后面表达式的值作为返回的对象的value属性值。
  2. 下次调用next方法时再继续往下执行,直到遇到下一个yield语句;
  3. 如果没有遇到新的yield语句,就一直运行到函数结束,直到遇到return语句为止,并将return语句后面的表达式的值作为返回对象的value属性值;
  4. 如果该函数没有return语句,则返回对象的value属性值为undefined

注意: yield语句为javascript提供了手动的 “惰性求值”

yield语句与return语句有相似之处也有区别,相似之处在于都返回紧跟在后面的值,区别在于return语句不具备记忆功能。

var arr = [1, [[2,3],4],[5,6]];
var flat = function* (a){
a.forEach(function(item){
if(typeof item !== 'number'){
yield* flat(item);
}else{
yield item;
}
});
} for(var f of flat(arr)){
console.log(f);
}

这个例子将会报错,因为forEach方法的参数是个普通的函数,但是里面使用了yield语句,普通函数里面是不允许是使用yield语句的。

那么我们来修改一下

var arr = [1, [[2,3],4],[5,6]];
var flat = function* (a){
var length = a.length;
for(var i =0; i < length; i++){
var item = a[i];
if(typeof item !== 'number'){
yield* flat(item);
}else{
yield item;
}
}
}; for(var f of flat(arr)){
console.log(f);
}// 1, 2, 3, 4, 5, 6
  • 与Iterator接口的关系

任意一个对象的Symbol.iterator方法等于该对象的遍历器对象生成函数,调用该函数会返回该对象的一个遍历器对象。

遍历器对象本身也有Symbol.iterator方法,执行后返回自身。

function* gen(){
//some code
}
var g = gen();
console.log(g[Symbol.iterator]() === g);

gen是一个generator函数,调用它会生成一个遍历器对象g,他的Symbol.iterator属性也是一个遍历器对象生成函数,执行后返回自己。

yield* 语句

如果在generator函数内部调用另一个generator函数,默认情况下是没有效果的。

  • yield*语句,专门用来在一个generator函数里面执行另一个generator函数。

      function* foo(){
    yield 'a';
    yield 'b';
    }
    function* bar(){
    yield 'x';
    yield* foo();
    yield 'y';
    } for(let v of bar()){
    console.log(v);
    }

上面将会返回x, a, b, y。如果直接调用foo函数的话,将不会有什么效果。

  • 如果yield命令后面没有星号,将返回一个遍历器对象,加上星号后将会返回遍历对象的具体值。yield* 语句相当于在generator函数内部部署了一个for...of循环。

      function* concat(iter1, iter2){
    yield* iter1;
    yield* iter2;
    }
    //等同于
    function* concat(iter1, iter2){
    for(var value of iter1){
    yield value;
    }
    for(var value of iter2){
    yield value;
    }
    }

还应注意的是,如果在遍历数组时,用yield命令将会返回全部都的数组成员,yield* 则返回单个字符:即数组的第一个成员。

  • 如果generator函数有return语句,那么将会返回相应的数据,如果return()不带任何参数,则相应位置返回的值为undefined。

  • yield* 命令可以很方便的取出嵌套数组的所有成员。

      function* iterTree(tree){
    if(Array.isArray(tree)){
    for(let i = 0; i < tree.length; i++){
    yield* iterTree(tree[i]);
    }
    }else{
    yield tree;
    }
    } const tree = ['a', ['b', 'c'], ['d', 'e']]; for(let x of iterTree(tree)){
    console.log(x);
    }// a b c d e

Generator函数的this

Generator函数总是返回一个遍历器,这个遍历器是generator函数的实例。

function* g(){
this.a = 11;
} let obj = g();
console.log(obj.a);//undefined

上面的代码中,函数g总是返回遍历器对象,而不是this对象,这时使用new命令就不能生成对应函数的实例,因为函数返回的是一个内部指针。如果想让generator函数能有正常的构造函数,就可以采用:先生成一个空对象,使用bind方法绑定generator函数内部的指针,这样,构造函数调用之后这个空对象就是generator函数的实例对象了。

function* F(){
yield this.x = 2;
yield this.y = 3;
}
var obj = {};
var f = F.bind(obj)(); f.next();
f.next();
f.next();
console.log(obj);//Object{value: 2, done: false}

通过generator函数部署Ajax操作

function* main(){
var result = yield request("http://some.url");
var resp = JSON.parse(result);
console.log(resp.value);
} function request(url){
makeAjaxCall(url, function(response){
it.next(response);
});
} var it = main();
it.next();

上面的main函数就是通过AJAX获取到的数据,makeAjaxCall函数的next方法中必须加上response参数,因为yield语句构成的表达式本身是没有值的,总是等于undefined。

Generator函数介绍的更多相关文章

  1. ES6 - Note7:Generator函数

    Generator函数 1.Generator函数是ES6增加的异步编程解决方案之一,与普通的函数行为完全不同,类似于一个状态机,内部封装了多个状态. 在函数定义的形式上,跟普通函数差不多,有两处不同 ...

  2. 转: ES6异步编程:Generator 函数的含义与用法

    转: ES6异步编程:Generator 函数的含义与用法 异步编程对 JavaScript 语言太重要.JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可. 以前,异步编程 ...

  3. Generator函数语法解析

    转载请注明出处: Generator函数语法解析 Generator函数是ES6提供的一种异步编程解决方案,语法与传统函数完全不同.以下会介绍一下Generator函数. 写下这篇文章的目的其实很简单 ...

  4. Generator函数异步应用

    转载请注明出处: Generator函数异步应用 上一篇文章详细的介绍了Generator函数的语法,这篇文章来说一下如何使用Generator函数来实现异步编程. 或许用Generator函数来实现 ...

  5. ES6的generator函数

    generator是什么? generator是ES6提供的一种异步编程解决方案,在语法上,可以把它理解为一个状态机,内部封装了多种状态.执行generator,会生成返回一个遍历器对象.返回的遍历器 ...

  6. ECMAScript 6 入门 ----Generator 函数

    本文转自:阮一峰老师的ECMAScript 6 入门,有时间可以看下评论! Generator 函数 简介 基本概念 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不 ...

  7. 一次搞懂 Generator 函数

    1.什么是 Generator 函数 在Javascript中,一个函数一旦开始执行,就会运行到最后或遇到return时结束,运行期间不会有其它代码能够打断它,也不能从外部再传入值到函数体内 而Gen ...

  8. ES 6 proimse &&iterator &&Generator函数 &&async

    1.proimse 异步调用function getData(){ let promise =new Promise((resolve,reject)); let xmlHttp =new XMLHt ...

  9. JavaScript中的Generator函数

    1. 简介 Generator函数时ES6提供的一种异步编程解决方案.Generator语法行为和普通函数完全不同,我们可以把Generator理解为一个包含了多个内部状态的状态机. 执行Genera ...

随机推荐

  1. Bootstrap支持的JavaScript插件

    1.导入JavaScript插件 Bootstrap除了包含丰富的Web组件之外,如前面介绍的下拉菜单.按钮组.导航.分页等.他还包括一些JavaScript的插件. Bootstrap的JavaSc ...

  2. Difference between .classpath and MANIFEST.MF

    What is the difference between adding a dependency jar to the .classpath file in a RAD project and a ...

  3. 怎样解决Please ensure that adb is correctly located at......

    昨天下午搭建了Android开发环境,但是天公不作美--执行新建的Android项目总是提演示样例如以下问题: [2014-10-30 15:41:47 - ] The connection to a ...

  4. idea中maven 加载spring-boot项目程序包找不到解决…

    首先检查maven配置对不对,包括被settings文件以及资源库的位置,maven版本等. 如果不行的话再进行下面的操作: 第一种方案: 在终端terminal中项目目录下,输入“mvn idea: ...

  5. mysql-5.7.16-linux-glibc2.5-x86_64精简后的主从配置

    1.创建复制账号,并授予复制权限CREATE USER 'fansik'@'10.%' IDENTIFIED BY 'fansik';GRANT REPLICATION SLAVE ON *.* TO ...

  6. python基础28 -----python中sockserver模块

    一.Python中的sockserver模块 1.该模块与sock模块不同之处是该模块自动帮我们分装好了一些功能,让我们在编程的时候直接调用这些功能就可以了,节省了编程步骤. 2.如图所示 注释:上图 ...

  7. Openstak(M版)计算节点安装

    #############修改hosts文件 10.0.0.11 controller10.0.0.31 compute110.0.0.32 compute210.0.0.41 block110.0. ...

  8. 值得关注的10个Python语言学习博客

    大家好,还记得我当时学习python的时候,我一直努力地寻找关于python的博客,但我发现它们的数量很少.这也是我建立这个博客的原因,向大家分享我自己学到的新知识.今天我向大家推荐10个值得我们关注 ...

  9. centos6 没有eth0网络

    编辑 /etc/sysconfig/network-scripts/ifcfg-eth0 ONREBOOT=no #改成yes service network restart 在用 ifconfig ...

  10. excel中如何取消自动超链接?

    最近做的表格有点多,年终述职也到了.总有一些地方生疏了,幸好还有点小印象.记录下来,以后可以回来看看. 方法一 适合单个链接的取消 1 输入网址后,按回车键确认,快捷键ctrl+z,即可取消,这种不好 ...