以下js代码在firefox,chrome和nodejs的开发人员控制台中也失败。无法找出原因?
function* x() {}
let y = x()
setTimeout(y.next, 100)
firefox错误
TypeError:调用了不兼容的CallGeneratorMethodIfWrapped方法 窗口
Chrome出现错误
未捕获的TypeError:调用了方法[Generator] .prototype.next 不兼容的接收器 在下一个()
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)
答案 0 :(得分:3)
将y
作为要调用的函数传递时,对象y.next
丢失。您可以这样做:
setTimeout(y.next.bind(y), 100)
当您传递y.next
时,它会到达y
对象上并获得对next
函数的引用,而它只会传递对next
函数的引用。它是对next
函数的通用引用,该函数与y
对象完全没有关联。然后,稍后触发setTimeout()
时,它仅自己调用next
函数,并且函数调用中未使用对象y
。这意味着执行next
时,this
的值将为undefined
,而不是适当的y
对象。
您可以想象这样做:
let x = y.next;
setTimeout(x, 100);
与y
无关的内容已传递给setTimeout()
。我们将把next()
方法称为普通函数。如果您这样做,可能会遇到相同的问题:
let x = y.next;
x();
根据其设计,setTimeout()
仅调用fn()
中的函数。它不会像y.next()
中那样调用方法。要调用方法,必须在实际的函数调用中使用对象引用,如在y.next()
中看到的那样。 setTimeout()
不会这样做。它只是调用函数。
因此,.bind()
创建了一个小的小存根函数,然后将为您正确调用它。因此,如我上面所示,使用它类似于:
let x = function() {
y.next();
}
setTimeout(x, 100);
或者,内联版本:
setTimeout(function() {
y.next();
}, 100);