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. CalendarUtil 日期操作工具类

    版权声明:本文为博主原创文章,未经博主允许不得转载. [java] view plain copy import java.util.Calendar; import java.text.DateFo ...

  2. Oracle数据库使用Analyze提升sql性能

    Oracle数据库使用Analyze提升sql性能 如果你不使用analyze完成sql优化,将意味着:你拒绝使用数据库的查询优化器,也失去了使用优化连接的机会.假设你创建了一张拥有100万条记录的临 ...

  3. Django 请求生命周期【图示】

    Django 请求生命周期

  4. 前端基础 & Bootstrap框架

    Bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支持响应式布局,并且 ...

  5. python构造wireshark可以解析的LTE空口数据

    Wireshark是可以解析LTE的空口数据.但是在wireshark的实现中,这些数据都是被封装到UDP报文中.然后根据wireshark的格式文件对LTE的数据加上头信息.头信息的定义参考附件pa ...

  6. Cocos2d-x3.0游戏实例之《别救我》第八篇——TiledMap实现关卡编辑器

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/musicvs/article/details/25368273 好吧.我真心全然搞不懂.我如今仅仅只 ...

  7. 《Mining of Massive Datasets》笔记(一)

    数据挖掘基本概念 数据挖掘定义 最广为接受得到定义是,数据挖掘是数据"模型"的发现过程.而"模型"却可以有多种含义. 1)统计建模 统计学家认为数据挖掘就是统计 ...

  8. eval in Shell

    语法:eval cmdLine eval会对后面的cmdLine进行两遍扫描,如果第一遍扫描后,cmdLine是个普通命令,则执行此命令: 如果cmdLine中含有变量的间接引用,则保证间接引用的语义 ...

  9. Python之模块和包(Day21)

    一.Python模块 Python模块(module),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句. 模块让你能够有逻辑的组织你的Python代码段 把相关的代 ...

  10. 爬虫基础库之Selenium

    1.简介 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作, ...