为什么生成器next函数不能成为事件监听器的回调函数

时间:2015-10-21 23:21:58

标签: javascript dom generator

我正在尝试使用发电机。当我尝试这段代码时,我遇到了意想不到的错误:

未捕获的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)

);

1 个答案:

答案 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 *