ES6新增----深入理解generator

参考学习:https://www.cnblogs.com/wangfupeng1988/p/6532713.html
https://www.cnblogs.com/diligenceday/p/5488037.html
http://www.ruanyifeng.com/blog/2015/04/generator.html
https://blog.csdn.net/hj7jay/article/details/53905868
先来一段最基础的Generator代码

function* Hello() {
    yield 100
    yield (function () {return 200})()
    return 300
}

var h = Hello()
console.log(typeof h)  // object

console.log(h.next())  // { value: 100, done: false }
console.log(h.next())  // { value: 200, done: false }
console.log(h.next())  // { value: 300, done: true }
console.log(h.next())  // { value: undefined, done: true }

Iterator遍历器
1.Symbol是一个特殊的数据类型,和number string等并列

// 数组
console.log([1, 2, 3][Symbol.iterator])  // function values() { [native code] }
// 某些类似数组的对象,NoeList
console.log(document.getElementsByTagName('div')[Symbol.iterator])  // function values() { [native code] }

2.在 ES6 中,原生具有[Symbol.iterator]属性数据类型有:数组、某些类似数组的对象(如arguments、NodeList)、Set和Map。其中,Set和Map也是 ES6 中新增的数据类型。

var item
for (item of [100, 200, 300]) {
    console.log(item)
}
// 打印出:100 200 300 
// 注意,这里每次获取的 item 是数组的 value,而不是 index ,这一点和 传统 for 循环以及 for...in 完全不一样

3.生成Iterator对象
定义一个数组,然后生成数组的Iterator对象

const arr = [100, 200, 300]
const iterator = arr[Symbol.iterator]()  // 通过执行 [Symbol.iterator] 的属性值(函数)来返回一个 iterator 对象

4.iterator,那么该如何使用它呢 ———— 有两种方式:next和for…of。
先说第一种,next

console.log(iterator.next())  // { value: 100, done: false }
console.log(iterator.next())  // { value: 200, done: false }
console.log(iterator.next())  // { value: 300, done: false }
console.log(iterator.next())  // { value: undefined, done: true }

再说第二种,for…of

let i
for (i of iterator) {
    console.log(i)
}
// 打印:100 200 300 

Generator
1.Generator,就是生成一个Iterator对象。因此才会有next(),也可以通过for…of来遍历。

function* Hello() {
    yield 100
    yield (function () {return 200})()
    return 300 
}
const h = Hello()
console.log(h[Symbol.iterator])  // [Function: [Symbol.iterator]]

2.const h = Hello()得到的就是一个iterator对象,因为h[Symbol.iterator]是有值的。既然是iterator对象,那么就可以使用next()和for…of进行操作

console.log(h.next())  // { value: 100, done: false }
console.log(h.next())  // { value: 200, done: false }
console.log(h.next())  // { value: 300, done: false }
console.log(h.next())  // { value: undefined, done: true }

let i
for (i of h) {
    console.log(i)
}

Generator 的具体应用
next和yield参数传递
1.yield后面的数据被返回,存放到返回结果中的value属性中。

function* G() {
    yield 100
}
const g = G()
console.log( g.next() ) // {value: 100, done: false}

2.还有另外一个方向的参数传递,就是next向yield传递。

function* G() {
    const a = yield 100
    console.log('a', a)  // a aaa
    const b = yield 200
    console.log('b', b)  // b bbb
    const c = yield 300
    console.log('c', c)  // c ccc
}
const g = G()
g.next()    // value: 100, done: false
g.next('aaa') // value: 200, done: false
g.next('bbb') // value: 300, done: false
g.next('ccc') // value: undefined, done: true

3.for…of的应用示例,用简单几行代码实现斐波那契数列。

function* fibonacci() {
    let [prev, curr] = [0, 1]
    for (;;) {
        [prev, curr] = [curr, prev + curr]
        // 将中间值通过 yield 返回,并且保留函数执行的状态,因此可以非常简单的实现 fibonacci
        yield curr
    }
}
for (let n of fibonacci()) {
    if (n > 1000) {
        break
    }
    console.log(n)
}

4.yield*语句,如果有两个Generator,想要在第一个中包含第二个,如下需求:

function* G1() {
    yield 'a'
    yield 'b'
}
function* G2() {
    yield 'x'
    yield 'y'
}
function* G1() {
    yield 'a'
    yield* G2()  // 使用 yield* 执行 G2()
    yield 'b'
}
function* G2() {
    yield 'x'
    yield 'y'
}
for (let item of G1()) {
    console.log(item)
}

5.Generator 不是函数,更不是构造函数,构造函数返回的是this,而Generator返回的是一个Iterator对象。完全是两码事,

猜你喜欢

转载自blog.csdn.net/weixin_41989325/article/details/89456092
今日推荐