Es6 generator浅入浅出

栏目: JavaScript · 发布时间: 5年前

内容简介:生成器是特殊的函数。生成器函数在执行时能暂停,后面又能从暂停处执行。 show me the coding调用生成器并不会执行函数,而是会返回一个迭代器,迭代器用来控制生成器的执行。调用迭代器的从执行上下文的角度来理解迭代器,创建迭代器的时候,生成器入栈,初始化参数(如果有的话),执行完毕后出栈,并且销毁当前执行环境,但是迭代器仍然保存着对他的引用,所以该环境并不会销毁,这个东西和闭包很像。换个角度来说,生成器需要恢复执行,所以环境不能销毁,保存在迭代器上。

生成器是特殊的函数。生成器函数在执行时能暂停,后面又能从暂停处执行。 show me the coding

function* zcGenerator() { // 这就是生成器
    yield 'ak-47'
}
复制代码

迭代器

const zcInterator = zcGenerator()
复制代码

调用生成器并不会执行函数,而是会返回一个迭代器,迭代器用来控制生成器的执行。调用迭代器的 next() 方法,会向生成器请求一个值,生成器内的语句执行到第一个 yield 的位置,并返回 yield 后跟的值,此时生成器异步挂起执行,直到下次再请求值,生成器恢复执行,如此循环下去,直到最后生成器执行完毕。 next() 方法返回一个对象 {value: '', done: ''} , value 表示本次 yield 返回的值, done 表示生成器后续时候还是有yield语句,即生成器是否执行完毕。

从执行上下文的角度来理解迭代器,创建迭代器的时候,生成器入栈,初始化参数(如果有的话),执行完毕后出栈,并且销毁当前执行环境,但是迭代器仍然保存着对他的引用,所以该环境并不会销毁,这个东西和闭包很像。换个角度来说,生成器需要恢复执行,所以环境不能销毁,保存在迭代器上。

function* weaponGenerator() {
  yield 'ak47'
  yield 'm16'
}
const weaponIterator = weaponGenerator()

console.log(weaponIterator.next()) // {value: 'ak47', done: false}
console.log(weaponIterator.next()) // {value: 'm16', done: false}
console.log(weaponIterator.next()) // {value: undefined, done: true}
复制代码

使用 yield* 表示将执行权交到另一个生成器函数(当前函数暂停执行)

function* weaponGeneratorInner() {
  yield 'g56'
  yield 'h58'
}

function* weaponGenerator() {
  yield 'ak47'
  yield* weaponGeneratorInner()
  yield 'm16'
}
const weaponIterator = weaponGenerator()

console.log(weaponIterator.next()) // {value: 'ak47', done: false}
console.log(weaponIterator.next()) // {value: 'g56', done: false}
console.log(weaponIterator.next()) // {value: 'm16', done: false}
console.log(weaponIterator.next()) // {value: 'h58', done: false}
console.log(weaponIterator.next()) // {value: undefined, done: true}
复制代码

迭代器与生成器交互

交互方式有三种

  1. 向生成器传递参数与生成器交互,像普通函数一样传递参数。
function* parGenerator(weapon) {
    yield weapon
}

const parIterator = parGenerator('j-20')
console.log(parIterator.next()) // { value: 'j-20', done: false }
复制代码
  1. 通过向 next() 传递参数,与生成器交互 next() 的参数会传递给当前生成器正在 yield 的值,因此,第一次调用 next() ,生成器并没有处于挂起的值,所以传递参数没有任何意义,调用完第一个 next() 方法,生成器开始执行,遇见第一个 yield ,函数挂起,并且返回当前值;第二次调用 next('j-30') , j-30 会替换掉当前 yield 的值 j-20 ,并继续往下执行,将 newWeapon 赋值为 j-30 ,生成器执行完毕。
function* parGenerator(weapon) {
  const newWeapon = yield weapon
  return newWeapon
}

const parIterator = parGenerator('j-20')
console.log(parIterator.next()) // { value: 'j-20', done: false }
console.log(parIterator.next('j-30')) // { value: 'j-30', done: true }
复制代码

注意:因为通过 next() 传递参数只能传递给当前生成器 yield 的值,因此第一次调用 next() 传递参数没有意义,所以,如果想为生成器提供一个初始值,可以向生成器函数穿第一个参数作为初始值。

  1. 通过迭代器的 throw 方法与生成器交互
function* throwGenerator() {
  try {
    yield 'good'
  } catch (err) {
    console.log(err)
  }
}

const throwInterator = throwGenerator()
console.log(throwInterator.next())
console.log(throwInterator.throw('bad'))
复制代码

thrownext 传参类似,只能对当前生成器 yield 的值 throw ,因此,在创建迭代器之后立即调用 throw 没有意义(会报错),换个角度来说,只有代码执行的时候才可以 try-catch ,在 throw 之前没有执行生成器, try-catch 也就没什么用。

注意: throw 必须在 next 之后调用,因为在调用第一个 next 之后,生成器在第一个 yield 处挂起,只有在请求下一个值或者 throw 的时候才会继续往后执行 try...catch... ,在throw的时候,生成器重新入栈,从 yield 'good' 的地方继续往后执行,生成器会将 yield 'good' 作为一个错误抛出,被 catch 抓住。

实例

  1. 生成id
function* idGenerator() {
  let id = 0
  while (true) {
    yield ++id
  }
}
const idIterator = idGenerator()

const id1 = idIterator.next().value
console.log(id1)
const id2 = idIterator.next().value
console.log(id2)
复制代码

因为yield会暂时挂起函数执行,所以 while 不会无限循环 2. 遍历dom节点

function* elementGenerator(element) {
  yield element
  element = element.firstElementChild
  while (element) {
    elementGenerator(element)
    element = element.nextElementSibling
  }
}

for (let elementGeneratorElement of elementGenerator()) {
  console.log(elementGeneratorElement.nodeName)
}
复制代码

以上所述就是小编给大家介绍的《Es6 generator浅入浅出》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

How Great Decisions Get Made

How Great Decisions Get Made

Maruska, Don / 2006-2 / $ 20.28

All too often, solving tough work issues can become a tug of war as clashing departments, priorities, personality styles, and other concerns threaten to destroy any possibility of a successful conclus......一起来看看 《How Great Decisions Get Made》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具