您的位置:首页 > Web前端 > JavaScript

JavaScript学习之路11_Generator

2015-11-24 22:29 701 查看

函数

先理解函数:

先看例子:

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

function foo(x){
return x*x;
}
var f1 = foo(2); //调用函数,结果是4


在调用函数的过程中,如果函数没有遇到return或者是隐含的return,那么控制权无法交回被调用的代码。

Generator

Generator其实和函数是很像的,看一下例子:

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


var f = fun(2);

f.next(); //3

f.next();//4

f.next();//5

备注:

Generator关键字是function*,要比function多一个*。

并且除了return,还可以使用yield返回多次。

举例说明:

//斐波拉契数列
//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){
t = a + b;
a = b;
b = t;
arr.push(t);
}
return arr;
}

//使用Generator
function* fib(max){
var
t,
a = 0,
b = 1,
n = 1;
while(n < max){
yield a;
t = a + b;
a = b;
b = t;
n++;
}
return n;
}


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

结果不是我们想要的,为什么呢?

直接调用一个generator和调用函数不一样,fib(5)仅仅是创建了一个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: true}


解析:

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

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

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


generator和普通函数相比,有什么用?

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

练习

要生成一个自增的ID,可以编写一个next_id()函数:

var current_id = 0;

function next_id() {
current_id ++;
return current_id;
}


由于函数无法保存状态,故需要一个全局变量current_id来保存数字。

不用闭包,试用generator改写:

function* next_id() {
var x = 1;
while(true){
yield x++;
}
}


测试就可以通过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript generator