I want to destructure the result of a previous yield using default values when the object is empty. But I'm getting a Cannot read property 'xxx' of undefined, meaning that where I try to destructure the variable theObject
is undefined, but why?
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}
}
The first yield returns me an empty object as expected, but then when I run the generator again I get the error that the first item (posX
) in the object destruction can not be read since the theObject
is undefined.
The problem is that you yield myObject
to the caller, the result of that yield
is read from the caller via next(/* this "undefined" argument gets passed into your generator function*/)
call. So theObject
is undefined
because you're not using the generator as intended.
When the iterator's next() method is called, the generator function's body is executed until the first yield expression, which specifies the value to be returned from the iterator
Calling the next() method with an argument will resume the generator function execution, replacing the yield expression where execution was paused with the argument from next()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
It's not very intuitive, generator functions are weird like that.
The following works but is probably not what you want as far as I understand
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}