为什么生成器的下一个函数不能是事件监听器的回调函数?

Why can't the generators next function be a callback function for an event listener

本文关键字:函数 事件 监听器 回调 不能 下一个 为什么      更新时间:2023-09-26

我尝试了一些生成器。当我尝试这段代码时,我得到了意想不到的错误:

Uncaught TypeError: Method [Generator].prototype。下一个调用不兼容的接收器#或在不兼容的HTMLButtonElement上调用CallStarGeneratorMethodIfWrapped方法

我的问题是,它不工作吗?这些错误消息背后的含义是什么?最重要的是;为什么是第一个()。接下来不作为正常函数处理吗?为什么addEventListener关心first()的起源?下一个函数。第一个类型()。接下来在控制台中。它写的是函数。下面是一个与下一个类似的注释函数,除了它总是产生相同的结果。

您可以尝试复制的代码:

<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>

另一种选择是将next与正确的上下文放在另一个函数中。为此,将迭代器存储在一个变量中。

var iterator = first();
document.getElementById("test").addEventListener('click',
    function (event){return iterator.next();}
    //context of next is always the correct one
);

如果这种情况经常发生,创建一个名为createNext的新函数是一个好主意,该函数以更纯的函数风格返回next函数

var createNext = function (generatorFunction){
    var iterator = generatorFunction();
    return function() {
        return iterator.next();
    };
};

document.getElementById("test").addEventListener('click',
    createNext(first)
);

jsFiddle Demo

事件监听的工作方式是,它将使用call调用函数句柄,并将this绑定从其执行上下文中分配给被调用的函数句柄。所以this将被绑定为next被调用的上下文。这就是为什么它不能正常工作。

接下来的问题是从生成器函数中实际获取函数以进行迭代。"调用生成器函数不会立即执行它的函数体;返回该函数的迭代器对象。"。这意味着,是的,first().next 一个函数对象,但它不是您想要传递的句柄。您只是想使用迭代器函数本身,但那将是first(),那么如果您希望它每次都调用next,该如何工作呢?

这里的一个选项是简单地使用生成器函数,然后将迭代器函数作为绑定传入。为了在.next内部维护迭代器函数的绑定,可以这样做:

document.getElementById("test").addEventListener('click', first().next.bind(first()));

first()的迭代器函数绑定到该迭代器函数的.next函数。有点乱。第一次调用first()公开迭代器函数,然后访问它的下一个函数,第二次调用只是将下一个函数的this绑定到迭代器函数,否则当eventListener使用call覆盖this绑定时,该函数将被覆盖。

你可以在这里阅读更多关于这些生成器函数和它们的迭代器的一般信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*