参考学习: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对象。完全是两码事,