【问题标题】:Can't destructure an object inside a function generator无法在函数生成器中解构对象
【发布时间】:2020-06-17 23:32:12
【问题描述】:

当对象为空时,我想使用默认值来解构先前收益的结果。但是我得到了一个无法读取未定义的属性“xxx”,这意味着我尝试解构变量theObject 的位置是未定义的,但为什么呢?

const DEFAULT_POSITION = {x: 20, y: 20}
const myObject = {}

function* myGenerator(i) {
  const theObject = yield myObject;
  const { posX = DEFAULT_POSITION.x, posY = DEFAULT_POSITION.y, scale = 1 } = theObject

  yield {posX, posY, scale}
}

第一个产量按预期返回一个空对象,但是当我再次运行生成器时,我得到一个错误,即对象销毁中的第一项 (posX) 无法读取,因为 theObject 未定义.

【问题讨论】:

  • 你是如何运行生成器的?请发布完整的代码。

标签: javascript ecmascript-6 generator


【解决方案1】:

问题是你yield myObject 调用者yield 的结果是通过next(/* this "undefined" argument gets passed into your generator function*/) 调用从调用者读取的。所以theObjectundefined 因为你没有按预期使用生成器。

当迭代器的 next() 方法被调用时,生成器函数的主体被执行,直到第一个 yield 表达式,它指定从迭代器返回的值

使用参数调用 next() 方法将恢复生成器函数的执行,将暂停执行的 yield 表达式替换为来自 next() 的参数

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

这不是很直观,生成器函数就是那样奇怪。

以下工作,但据我了解可能不是您想要的

const DEFAULT_POSITION = {x: 20, y: 20}
const myObject = {}

function* myGenerator(i) {
  const theObject = yield
  const { posX = DEFAULT_POSITION.x, posY = DEFAULT_POSITION.y, scale = 1 } = theObject

  yield {posX, posY, scale}
}
const it = myGenerator()
console.log(it.next()) // -> {value: undefined, done: false}
console.log(it.next(myObject)) // -> {value: { posX: 20, posY: 20, scale: 1 }, done: false}

【讨论】:

  • 感谢 sn-p 的东西 :-)
  • 我明白了。谢谢你的解释。我在代码审查中审查了 redux-saga 的工作,但在我提出使用解构的建议之前,我只想在 chrome 控制台上单独测试它并遇到了我描述的问题。我将等待,看看它在审查中的进展情况,并很快回到这个问题。
【解决方案2】:

了解生成器

yield 的一种思考方式是作为断点,它将一个值返回给调用主体。它也可以在生成器主体中传递一个值,但该值需要使用next() 传递,如MDN: Generator#next 中所述:

variable = yield expression中,传递给.next()函数的值将被赋值给变量。

在您的情况下,没有传递给 next() 的值(至少在您给定的代码中没有),所以 theObjectundefined 并且在重组分配中使用时遇到错误。

我尝试在两个示例中重新编写您的代码,带和不带参数传递给它以进行初始化,然后进行一些循环以演示使用以前的值。


没有参数传递给生成器

以下代码不向生成器函数传递任何参数。多个 yield 旨在展示 Generator 的返回值。

function* GetPositions(args={}) {
  const defaults = {x:20,y:20}
  const position = Object.assign({}, defaults, args)
  yield position             // return initial setup
  
  const { x:posX, y:posY, scale = 1 } = position
  yield {posX, posY, scale}  // return next value
}


let coord = GetPositions()
console.log( coord.next().value )  // {x:20, y:20}
console.log( coord.next().value )  // {posX:20, posY:20, scale:1}

将参数传递给生成器

以下将一个对象传递给生成器函数。它只是一个部分对象,因为它包含一个用于演示使用内部默认值的键。

function* GetPositions(args={}) {
  const defaults = {x:20,y:20}
  const position = Object.assign({}, defaults, args)
  yield position             // return initial setup
  
  const { x:posX, y:posY, scale = 1 } = position
  yield {posX, posY, scale}  // return next value
}

let coord = GetPositions({x:1})   // initial argument
console.log( coord.next().value ) // {x:1, y:20}
console.log( coord.next().value ) // {posX:1, posY:20, scale:1}

在生成器中循环

这将更接近于您可能使用生成器的目的,因为更常见的是以重复方式使用生成器来生成序列或高级值。

function* GetPositions(args={}) {
  const defaults = {x:20,y:20}
  const position = Object.assign({}, defaults, args)
  let { x:posX, y:posY, scale = 1 } = position
  
  yield {posX, posY, scale}
  
  while(true){
    posX+=5, posY+=5
    yield {posX, posY, scale}     // return next value
  }
}

let coord = GetPositions({x:1})   // initial argument

console.log( coord.next().value ) // {posX:1,  posY:20, scale:1}
console.log( coord.next().value ) // {posX:6,  posY:25, scale:1}
console.log( coord.next().value ) // {posX:11, posY:30, scale:1}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 2018-07-12
    • 2011-08-21
    • 1970-01-01
    相关资源
    最近更新 更多