Generator函数语法解析 (3)

如果在Generator函数中存在return语句,则需要使用let value = yield* iterator方式获取返回值。

function *foo () { yield 1 return 2 } function *gen () { var x = yield* foo() return x } const g = gen() g.next() // {value: 1, done: false} g.next() // {value: 2, done: true}

使用yield*表达式可以很方便的取出嵌套数组的成员。

// 普通方法 const arr = [1, [[2, 3], 4]] const str = arr.toString().replace(/,/g, '') for (let item of str) { console.log(+item) // 1, 2, 3, 4 } // 使用yield*表达式 function *gen (arr) { if (Array.isArray(arr)) { for (let i = 0; i < arr.length; i++) { yield * gen(arr[i]) } } else { yield arr } } const g = gen([1, [[2, 3], 4]]) for (let item of g) { console.log(item) // 1, 2, 3, 4 } 与Iterator接口的关系

任何一个对象的属性,指向默认的遍历器对象生成函数。而Generator函数也是遍历器对象生成函数,所以可以将Generator函数赋值给Symbol.iterator属性,这样就使对象具有了Iterator接口。默认情况下,对象是没有Iterator接口的。
具有Iterator接口的对象,就可以被,,和循环遍历了。

const person = { name: 'keith', height: 180 } function *gen () { const arr = Object.keys(this) for (let item of arr) { yield [item, this[item]] } } person[Symbol.iterator] = gen for (let [key, value] of person) { console.log(key, value) // name keith , height 180 }

Generator函数函数执行之后,会返回遍历器对象。该对象本身也就有Symbol.iterator属性,执行后返回自身

function *gen () {} const g = gen() g[Symbol.iterator]() === g // true for...of循环

for...of循环可以自动遍历Generator函数生成的Iterator对象,不用调用next方法。

function *gen () { yield 1 yield 2 yield 3 return 4 } for (let item of gen()) { console.log(item) // 1 2 3 }

上面代码使用for...of循环,依次显示 3 个yield表达式的值。这里需要注意,一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for...of循环之中。

作为对象属性的Generator函数

如果一个对象有Generator函数,那么可以使用简写方式

let obj = { * gen () {} } // 也可以完整的写法 let obj = { gen: function *gen () {} }

当然了,如果是在构造函数中,简写形式也是一样的。

class F { * gen () {} } Generator函数中的this

Generator函数中的this对象跟构造函数中的this对象有异曲同工之处。先来看看构造函数中的new关键字的工作原理。

function F () { this.a = 1 } const f = new F()

调用构造函数F,返回实例对象f

将构造函数内部中的this指向这个实例对象

将构造函数中的原型对象赋值给实例对象的原型

执行构造函数中的代码

调用Generator函数会返回遍历器对象,而不是实例对象,因此无法获取到this指向的实例对象上的私有属性和方法。但是这个遍历器对象可以继承Generator函数的prototype原型对象上的属性和方法(公有属性和方法)。

function *Gen () { yield this.a = 1 } Gen.prototype.say = function () { console.log('keith') } const g = new Gen() g.a // undefined g.say() // 'keith'

如果希望修复this指向性问题,可以使用call方法将函数执行时所在的作用域绑定到Generator.prototype原型对象上。这样做,会使私有属性和方法变成公有的了,因为都在原型对象上了。

function *Gen () { this.a = 1 yield this.b = 2 yield this.c = 3 } const g = Gen.call(Gen.prototype) g.next() // {value: 2, done: false} g.next() // {value: 3, done: false} g.next() // {value: undefined, done: true} g.a // 1,继承自Gen.prototype g.b // 2,同上 g.c // 3,同上 应用

Generator函数的应用主要在异步编程上,会在下一篇文章中分享。请期待噢: )

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzdfx.html