JS之Generator(生成器)
这阵子因为要学习React Native,而RN必备的知识就是JS,所以开始学习起来了Js,在此声明写博客就是为了更好的学习,总结一些我学习过程中知识点,有不同意见的请尽情发表!
1. 概述
function* gen(x){
var y = yield x + 2;
return y;
}
上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。其实整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用 yield 语句注明。Generator 函数的执行方法如下:
function* gen(x){
var y = yield x + 2;
return y;
}
var g = gen(1);
console.log(g.next());//返回 对象 {value : 3, done : false }
console.log(g.next());//返回 对象 {value : undefined, done : false }
如图:
上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止,再次调用g的next的方法,内部指针指向下个yield语句。
换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,这个对象就是具有两个属性(done (done=false) 和 value (value=operand))的 IteratorResult 对象。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。这里说明了Generator 函数可以暂停执行和恢复执行,这是它能封装异步任务的根本原因。
2.迭代器委托
使用yield*可以实现迭代器之间的委托,语法 : yield* 迭代器
function* stringIter() { var str = "bobsyouruncle"; var idx = 0; while(idx < str.length) yield str[idx++]; }
function* strIter() { yield "jo"; yield* stringIter(); } var si2 = strIter(); console.log(si2.next().value); console.log(si2.next().value); console.log(si2.next().value); console.log(si2.next().value);
输出:
jo
b
o
b
上面的代码则 yield* 委托到 stringIter 生成器。
3.next传递参数
还可以将参数传递给 next 并使用该参数修改生成器的状态,以创建更高级的生成器。 next 将成为之前执行的 yield 表达式的结果值。在下面的示例中,当你将值 100 传递给 next 方法时,会重置生成器的内部索引值。如下代码:
function
* strIter2() {
var
str =
"jobob"
;
var
idx = 0;
while
(idx < str.length) {
var
modify = yield str[idx++];
if
(modify == 100) {
idx = 0;
}
}
}
var
str2 = strIter2();
console.log(str2.next().value);
console.log(str2.next().value);
console.log(str2.next().value);
console.log(str2.next(100).value);
输出:
j
o
b
j
上面的代码给next传递100,内部索引值会被重置为0.
4.throw
genrator还可以处理错误代码:
function* genthrow(x){
try {
var y = yield x + 2;
} catch (e){
console.log("genthrow--------->" + e);
}
return y;
}
var thro = genthrow(1);
thro.next();
thro.throw("出错了")
上面代码的最后一行,Generator 函数体外,使用指针对象的 throw 方法抛出的错误,可以被函数体内的 try ... catch 代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。