我正在尝试使用发电机。当我尝试这段代码时,我遇到了意想不到的错误:
未捕获的TypeError:在不兼容的接收器上调用的方法[Generator] .prototype.next# 要么 TypeError:在不兼容的HTMLButtonElement上调用CallStarGeneratorMethodIfWrapped方法
我的问题,它不起作用吗?这些错误消息背后的含义是什么?最重要的是;为什么first()。next不作为普通函数处理?为什么addEventListener关心first()。next函数的起源。在控制台中键入first()。next。它说功能。下面列出了与下一个相似的功能,除了它产生的结果总是相同。
您可以尝试重现的代码:
<html>
<button id="test">Click</button>
<script>
var first = function* (){
console.log("first click");
yield true;
console.log("second click");
yield true;
};
document.getElementById("test").addEventListener('click', first().next);
/*var wouldwork = function (){
console.log("would work");
return { value: true, done: false };
// same as the next returns
};*/
/*document.getElementById("test").addEventListener('click', wouldwork);*/
</script>
</html>
另一种选择是将下一个正确的上下文放在另一个函数中。为此,我们将迭代器存储在变量中。
var iterator = first();
document.getElementById("test").addEventListener('click',
function (event){return iterator.next();}
//context of next is always the correct one
);
如果更频繁地发生这种情况,最好创建一个名为createNext的新函数,该函数以更纯粹的函数样式返回下一个函数
var createNext = function (generatorFunction){
var iterator = generatorFunction();
return function() {
return iterator.next();
};
};
document.getElementById("test").addEventListener('click',
createNext(first)
);
答案 0 :(得分:1)
<强> jsFiddle Demo
强>
事件侦听的工作方式是它将使用call
调用函数句柄,并将this
绑定从其执行上下文分配给被调用的函数句柄。所以this
将被绑定为next
被调用的上下文。这就是为什么它没有像书面那样工作。
接下来,存在实际从生成器函数获取函数以进行迭代的问题。 &#34;调用生成器函数不会立即执行其正文;而是返回该函数的迭代器对象。&#34; 。这意味着是的,first().next
是一个函数对象,但它不是你要传递的句柄。您只想使用迭代器函数本身,但那将是first()
,那么如果您希望每次都调用它,那么它是如何工作的呢?
这里的一个选项就是获取你的生成器函数,并在稍后作为绑定传递迭代器函数。为了保持迭代器函数在.next
内部的绑定,你可以这样做:
document.getElementById("test").addEventListener('click', first().next.bind(first()));
这会将first()
的迭代器函数绑定到迭代器函数的.next
函数。有点乱。第一次调用first()会暴露迭代器函数然后访问它的下一个函数,第二次调用只是将下一个函数this
绑定到迭代器函数,当eventListener覆盖{{{}时,它会被覆盖。使用this
进行绑定。
您可以在此处详细了解这些生成器函数及其迭代器:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function *