当前位置:K88软件开发文章中心编程语言JavaScriptECMAScript → 文章内容

ECMAScript 6 Generator 函数

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 15:38:37

错误,也可以被函数体外的catch捕获。function *foo() { var x = yield 3; var y = x.toUpperCase(); yield y;}var it = foo();it.next(); // { value:3, done:false }try { it.next(42);} catch (err) { console.log(err);}上面代码中,第二个next方法向函数体内传入一个参数42,数值是没有toUpperCase方法的,所以会抛出一个TypeError错误,被函数体外的catch捕获。一旦Generator执行过程中抛出错误,且没有被内部捕获,就不会再执行下去了。如果此后还调用next方法,将返回一个value属性等于undefined、done属性等于true的对象,即JavaScript引擎认为这个Generator已经运行结束了。function* g() { yield 1; console.log('throwing an exception'); throw new Error('generator broke!'); yield 2; yield 3;}function log(generator) { var v; console.log('starting generator'); try { v = generator.next(); console.log('第一次运行next方法', v); } catch (err) { console.log('捕捉错误', v); } try { v = generator.next(); console.log('第二次运行next方法', v); } catch (err) { console.log('捕捉错误', v); } try { v = generator.next(); console.log('第三次运行next方法', v); } catch (err) { console.log('捕捉错误', v); } console.log('caller done');}log(g());// starting generator// 第一次运行next方法 { value: 1, done: false }// throwing an exception// 捕捉错误 { value: 1, done: false }// 第三次运行next方法 { value: undefined, done: true }// caller done上面代码一共三次运行next方法,第二次运行的时候会抛出错误,然后第三次运行的时候,Generator函数就已经结束了,不再执行下去了。Generator.prototype.return()Generator函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历Generator函数。function* gen() { yield 1; yield 2; yield 3;}var g = gen();g.next() // { value: 1, done: false }g.return('foo') // { value: "foo", done: true }g.next() // { value: undefined, done: true }上面代码中,遍历器对象g调用return方法后,返回值的value属性就是return方法的参数foo。并且,Generator函数的遍历就终止了,返回值的done属性为true,以后再调用next方法,done属性总是返回true。如果return方法调用时,不提供参数,则返回值的value属性为undefined。function* gen() { yield 1; yield 2; yield 3;}var g = gen();g.next() // { value: 1, done: false }g.return() // { value: undefined, done: true }如果Generator函数内部有try...finally代码块,那么return方法会推迟到finally代码块执行完再执行。function* numbers () { yield 1; try { yield 2; yield 3; } finally { yield 4; yield 5; } yield 6;}var g = numbers()g.next() // { done: false, value: 1 }g.next() // { done: false, value: 2 }g.return(7) // { done: false, value: 4 }g.next() // { done: false, value: 5 }g.next() // { done: true, value: 7 }上面代码中,调用return方法后,就开始执行finally代码块,然后等到finally代码块执行完,再执行return方法。yield*语句如果在Generater函数内部,调用另一个Generator函数,默认情况下是没有效果的。function* foo() { yield 'a'; yield 'b';}function* bar() { yield 'x'; foo(); yield 'y';}for (let v of bar()){ console.log(v);}// "x"// "y"上面代码中,foo和bar都是Generator函数,在bar里面调用foo,是不会有效果的。这个就需要用到yield*语句,用来在一个Generator函数里面执行另一个Generator函数。function* bar() { yield 'x'; yield* foo(); yield 'y';}// 等同于function* bar() { yield 'x'; yield 'a'; yield 'b'; yield 'y';}// 等同于function* bar() { yield 'x'; for (let v of foo()) { yield v; } yield 'y';}for (let v of bar()){ console.log(v);}// "x"// "a"// "b"// "y"再来看一个对比的例子。function* inner() { yield 'hello!';}function* outer1() { yield 'open'; yield inner(); yield 'close';}var gen = outer1()gen.next().value // "open"gen.next().value // 返回一个遍历器对象gen.next().value // "close"function* outer2() { yield 'open' yield* inner() yield 'close'}var gen = outer2()gen.next().value // "open"gen.next().value // "hello!"gen.next().value // "close"上面例子中,outer2使用了yield*,outer1没使用。结果就是,outer1返回一个遍历器对象,outer2返回该遍历器对象的内部值。从语法角度看,如果yield命令后面跟的是一个遍历器对象,需要在yield命令后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*语句。let delegatedIterator = (function* () { yield 'Hello!'; yield 'Bye!';}());let delegatingIterator = (function* () { yield 'Greetings!'; yield* delegatedIterator; yield 'Ok, bye.';}());for(let value of delegatingIterator) { console.log(value);}// "Greetings!// "Hello!"// "Bye!"// "Ok, bye."上面代码中,delegatingIterator是代理者,delegatedIterator是被代理者。由于yield* delegatedIterator语句得到的值,是一个遍历器,所以要用星号表示。运行结果就是使用一个遍历器,遍历了多个Generator函数,有递归的效果。yield*后面的Generator函数(没有return语句时),等同于在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*后面的Generator函数(没有return语句时),不过是for...of的一种简写形式,完全可以用后者替代前者。反之,则需要用var value = yield* iterator的形式获取return语句的值。如果yield*后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员。function* gen()

上一页  [1] [2] [3] [4] [5] [6] [7]  下一页


ECMAScript 6 Generator 函数