在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意!

如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/学习。


generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。

我们先看一下函数的概念:

一个函数是一段完整的代码,调用一个函数就是传入参数,然后返回结果。

function foo(x) {
return x + x;
} var r = foo(1); // 调用foo函数

在函数执行过程中,如果没有遇到 return 语句,控制权无法交回被调用的代码。(函数末尾如果没有return,就是隐含的return undefined;

generator定义

function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}

generator与函数的区别

generator由 function* 定义(注意多出的*号),并且,除了 return 语句,还可以用 yield 返回多次。

举个例子就容易理解了:

著名的斐波拉切数列,它是由0,1开头:

0 1 1 2 3 5 8 13 21 34 ...

要编写一个产生斐波那契数列的函数,可以这么写:

function fib(max) {
var
t,
a = 0,
b = 1,
arr = [0, 1];
while (arr.length < max) {
[a, b] = [b, a + b];
arr.push(b);
}
return arr;
} // 测试:
fib(5); // [0, 1, 1, 2, 3]
fib(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

函数只能返回一次,所以必须返回一个Array

但是,如果换成generator,就可以一次返回一个数,不断返回多次。用generator改写如下:

'use strict'
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 0;
while (n < max) {
yield a;
[a, b] = [b, a + b];
n ++;
}
return;
}

直接调用:

fib(5); // fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window}

我们发现,直接调用一个generator和调用函数不一样, fib(5) 仅仅是创建了一个generator对象,还没有去执行它。

调用generator对象有两个方法:

一是不断地调用generator对象的 next() 方法:

var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}

next() 方法会执行generator的代码,然后,每次遇到 yield x; 就返回一个对象 {value: x, done: true/false} ,然后“暂停”。返回的 value 就是 yield 的返回值, done 表示这个generator是否已经执行结束了。如果 done 为 true ,则 value 就是 return 的返回值。

当执行到 done 为 true 时,这个generator对象就已经全部执行完毕,不要再继续调用 next() 了。

二是直接用 for......of 循环迭代generator对象,这种方式不需要我们自己加判断 done :

for (var x of fib(10)) {
console.log(x); // 依次输出0, 1, 1, 2, 3, ...
}

generator优点

1.正是由于generator在执行过程中能多次返回,所以它看上去像一个可以记住执行状态的函数,利用这一点,可以通过写一个generator来实现需要用面向对象才能实现的功能。

比如,用一个对象来保存状态,我们一般是用对象的属性来保存。这样很繁琐:

var fib = {
a: 0,
b: 1,
n: 0,
max: 5,
next: function () {
var
r = this.a,
t = this.a + this.b;
this.a = this.b;
this.b = t;
if (this.n < this.max) {
this.n ++;
return r;
} else {
return undefined;
}
}
};

2.generator还有另一个巨大的好处,就是把异步回调代码变成“同步”代码。

没有generator时,用AJAX时需要这么写代码:

ajax('http://url-1', data1, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-2', data2, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-3', data3, function (err, result) {
if (err) {
return handle(err);
}
return success(result);
});
});
});

回调越多,代码越难看。

通过使用generator时,可以这么写:

try {
r1 = yield ajax('http://url-1', data1);
r2 = yield ajax('http://url-2', data2);
r3 = yield ajax('http://url-3', data3);
success(r3);
}
catch (err) {
handle(err);
}

看上去是同步的代码,实际上是异步的代码。

JavaScript学习笔记(十三)——生成器(generator)的更多相关文章

  1. Python学习笔记014——生成器Generator

    1 生成器定义 在Python中,一边循环一边计算的机制,称之为生成器(generator). 生成器是一个迭代器. 含有yield语句的函数是生成器函数,该函数被调用时返回一个生成器对象(yield ...

  2. javascript学习笔记(四) Number 数字类型

    数字格式化方法toFixed().toExponential().toPrecision(),三个方法都四舍五入 toFixed() 方法指定小数位个数  toExponential() 方法 用科学 ...

  3. ES6学习笔记<三> 生成器函数与yield

    为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...

  4. JavaScript学习笔记[0]

    JavaScript学习笔记[0] 使用的是廖雪峰JavaScript教程. 数据类型 Number 表示数字,不区分浮点整形. === 比较时不转化数据类型. == 反之. NaN与任何值都不想等, ...

  5. python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容

    python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...

  6. Java程序猿的JavaScript学习笔记(汇总文件夹)

    最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...

  7. Java程序猿的JavaScript学习笔记(8——jQuery选择器)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  8. Java程序猿JavaScript学习笔记(2——复制和继承财产)

    计划和完成在这个例子中,音符的以下序列: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaSc ...

  9. java之jvm学习笔记十三(jvm基本结构)

    java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...

  10. Java程序猿的JavaScript学习笔记(3——this/call/apply)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

随机推荐

  1. sys.argv向脚本中传递参数

    可以向脚本中传递无限多个参数,其值是一个列表,默认sys.argv[0]内容是脚本文件路径加文件名 test.py文件中的内容如下: #! /usr/bin/python3import sys pri ...

  2. VS连接数据库的通用方法(SQL/MySql)

    在vs里面连接数据库的方法有很多,这里是通用的方法和基本操作 SQL /// <summary> /// 数据访问抽象基础类 /// Copyright (C) Maticsoft /// ...

  3. 设计模式:基于线程池的并发Visitor模式

    1.前言 第二篇设计模式的文章我们谈谈Visitor模式. 当然,不是简单的列个的demo,我们以电商网站中的购物车功能为背景,使用线程池实现并发的Visitor模式,并聊聊其中的几个关键点. 一,基 ...

  4. js修改title

    document.title = 'xxxxxx';

  5. PHP的Session机制

    客户端浏览器和服务器之间通信使用的http协议是一种无状态的协议,在它看来,客户端发起的每个请求都是独立.没有关联的.然而,在实际的Web应用开发中,服务器却经常需要根据用户以往的一些状态或数据对请求 ...

  6. 基于Vue.js的大型报告页项目实现过程及问题总结(一)

    今年5月份的时候做了一个测评报告项目,需要在网页正常显示的同时且可打印为pdf,当时的技术方案采用jquery+template的方式,因为是固定模板所以并没有考虑报告的模块化区分,九月底产品提出新的 ...

  7. Javaweb项目开发的前后端解耦的必要性

    JavaWeb项目为何我们要放弃jsp?为何要前后端解耦?为何要动静分离? 使用jsp的痛点: 1.jsp上动态资源和静态资源全部耦合在一起,服务器压力大,因为服务器会收到各种静态资源的http请求, ...

  8. Codeforces Round #383 (Div. 2)C. Arpa's loud Owf and Mehrdad's evil plan

    C. Arpa's loud Owf and Mehrdad's evil plan time limit per test 1 second memory limit per test 256 me ...

  9. linux tar命令 压缩、打包、解压 详解

    linux tar命令 压缩.打包.解压 详解 1.常用压缩命令 tar –czvf 压缩后的文件.tar.gz 要压缩的文件 2.常用解压命令 tar –xzvf 解压后的文件.tar.gz [要解 ...

  10. Oracle-1 - :超级适合初学者的入门级笔记,CRUD,事务,约束 ......

    Oracle 更改时间: 2017-10-25  -  21:33:49 2017-10-26  -  11:43:19 2017-10-27  -  19:06:57 2017-10-28  -  ...