The following js code fails in developer console of firefox, chrome and nodejs as well. Unable to figure out why?
function* x() {}
let y = x()
setTimeout(y.next, 100)
Error in firefox
TypeError: CallGeneratorMethodIfWrapped method called on incompatible Window
Error in chrome
Uncaught TypeError: Method [Generator].prototype.next called on incompatible receiver # at next ()
Error in node.js
timers.js:475
timer._onTimeout();
^
TypeError: Method [Generator].prototype.next called on incompatible receiver #<Timeout>
at Timeout.next [as _onTimeout] (<anonymous>)
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
at Timer.listOnTimeout (timers.js:270:5)
The object
y
is lost when you passy.next
as the function to be called. You can do this:When you pass
y.next
, it reaches onto they
object and gets a reference to thenext
function and it passes just a reference to thenext
function. It's a generic reference to thenext
function that has no association at all with they
object. Then, later when thesetTimeout()
fires, it just calls thenext
function all by itself and the objecty
is not used in the function call. That means that whennext
executes, thethis
value will beundefined
and will not be the appropriatey
object.You can imagine it doing this:
Nothing to do with
y
was passed tosetTimeout()
. It's going to call thatnext()
method as a normal function. You could see the same problem if you did this:By its design,
setTimeout()
just calls functions as infn()
. It doesn't call methods as iny.next()
. To call a method, the object reference has to be used in the actual function call as you see iny.next()
.setTimeout()
does not do that. It just calls functions.So,
.bind()
creates a small little stub function that will then call it properly for you. So, using it as I showed above is analogous to this:Or, the inline version: