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
yis lost when you passy.nextas the function to be called. You can do this:When you pass
y.next, it reaches onto theyobject and gets a reference to thenextfunction and it passes just a reference to thenextfunction. It's a generic reference to thenextfunction that has no association at all with theyobject. Then, later when thesetTimeout()fires, it just calls thenextfunction all by itself and the objectyis not used in the function call. That means that whennextexecutes, thethisvalue will beundefinedand will not be the appropriateyobject.You can imagine it doing this:
Nothing to do with
ywas 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: