es6的学习笔记(五):generator

generator是一个简单的生成符合iterator协议的新特性。它可以方便的生成iterator,具有iterator的特性,也就是具有[Symbol.iterator],同时也有next()函数,同时可以使用for of,Array.from,[…]等操作。
调用generator函数,返回一个iterator对象,执行next()函数,会返回{value:value,done:boolean}。内部通过yield产生value,实例如下:

function* gen(){
  yield 'hello'
  yield 'hi'
  return 'byebye'
};
let g = gen();
console.log(g.next().value);//hello
console.log(g.next().value);//hi
console.log(g.next().value);//byebye
console.log(g.next().value);//undefined
console.log(g.next().value);//undefined

其中,迭代器的next()执行顺序如下:

  1. 遇到yield语句,暂停执行后面的操作,并把紧跟在yield后面的值作为返回值。
  2. 下一次调用next()方法时,再继续往下运行,直到遇到下一个yield,如果next()函数有参数,则在一定条件下会进行赋值操作,然后再继续执行,第一次next的参数是无效的
  3. 如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
  4. 如果该函数没有return语句,则返回的对象的value属性值为undefined。
var arr = [1, [[2, 3], 4], [5, 6]];

var flat = function* (a) {
  var length = a.length;
  for (var i = 0; i < length; i++) {
    let y;
    var item = a[i];
    if (typeof item !== 'number') {
      y=yield* flat(item);
      console.log(y)
    } else {
      y=yield item;
      console.log(y);
    }
  }
};

const s=flat(arr);
console.log(s.next('hi1').value); //1
console.log(s.next('hi2').value); //hi2  2
console.log(s.next('hi3').value); //hi3  3
const answers = [
  `It is certain`,
  `Yes definitely`,
  `Most likely`,
  `Yes`,
  `Ask again later`,
  `Better not tell you now`,
  `Cannot predict now`,
  `Don't count on it`,
  `My sources say no`,
  `Very doubtful`
]
function answer () {
  return answers[Math.floor(Math.random() * answers.length)]
}
console.log(answer()) //每次运行都随机产生一句话

这个时候,可以写一个generator来产生一个无限序列,序列内容就是一个个随机的回答。generator的形式如下:

//version1
function* ball(){
  while(true)
    yield `[a] ${answer()}`
}
const g = ball();
console.log(g.next().value);
console.log(g.next().value);//随机产生一个回答

//version2
function* ball(){
  let question;
  while(true){
    question = yield `[a] ${answer()}`
    console.log(`[q] ${ question }`)
  }
}
const g = ball()
g.next();//跳过第一个,因为第一个输入值不会影响输出,具体原因有待回头继续研究
console.log(g.next('hello?').value)//先输出[q],在输出[a]
console.log(g.next('hi?').value)

关于generator还有很多内容,有待后续继续挖掘