在上一篇文章中,我们简单了解了 ES6 生成器。在这一篇文章章中,我将使用 ES5 的代码实现 ES6 生成器的部分功能。推荐大家去阅读《你不知道的 JavaScript 中卷》,书上有关于生成器的更详细的介绍,我下面用到的代码是书上的示例代码。
要实现一个生成器,我们首先要确定需要实现哪几个功能,然后再一步步实现。这里重点实现两个功能:数据的双向传递和暂停。
function *func() {
var num = yield '传出的值';
console.log(num);
}
ES6 生成器的代码像上面这样。由于代码都是顺序执行的,如果想要实现暂停,我们就要能够保存状态。可以用一个名为 state 的变量保存状态。但是,如何在生成器外部调整状态呢?这里我们用到了闭包。
具体代码实现如下,若函数 foo 是一个生成器,它首先要返回一个对象,该对象包括一个 next 函数,调用函数可以返回 value
return {
next:function(v) {
return {
value:........
}
},
}
其次,foo 要包含一个处理不同状态的程序,可以用 switch 语句实现:
// 管理生成器状态
var state;
// 生成器变量范围声明
var val;
//处理每个状态
function process(v) {
switch (state) {
case 1:
return '传出的值';
case 2:
val = v;
console.log(val);
return;
case 3:
var err = v;
console.log("oops:", err);
return false;
}
}
然后,在 next 函数中针对不同的状态进行处理:
if (!state) {
state = 1;
return {
done: false,
value: process(), //第一个状态返回对象的 value 为 request(url)
}
}
// yield 恢复
else if (state == 1) {
state = 2;
return {
done: true, // 第二个状态表示第二次调用 next ,此时生成器为完成状态
value: process(v) // 第二个状态返回的对象的 value 为 undefined
}
}
// 此处生成器已经完成
else {
return {
done: true,
value: undefined
}
}
代码整合为:
function foo(url) {
// 管理生成器状态
var state;
// 生成器变量范围声明
var val;
//处理每个状态
function process(v) {
switch (state) {
case 1:
return '传入的值';
case 2:
val = v;
console.log(val);
return;
case 3:
var err = v;
console.log("oops:", err);
return false;
}
}
return {
// 此处利用了闭包来保存状态,每次调用 next 都会进入不同的状态,模拟了迭代器的功能
next: function(v) {
// 初始状态,执行到 yield
if (!state) {
state = 1;
return {
done: false,
value: process(), //第一个状态返回对象的 value 为 request(url)
}
}
// yield 恢复
else if (state == 1) {
state = 2;
return {
done: true, // 第二个状态表示第二次调用 next ,此时生成器为完成状态
value: process(v) // 第二个状态返回的对象的 value 为 undefined
}
}
// 此处生成器已经完成
else {
return {
done: true,
value: undefined
}
}
}
var it = foo(3);
it.next();
it.next(6);
这段代码与最上方 ES6 生成器代码的功能相同。
网友评论