有没有办法用Plain JS实现EventTarget?

时间:2014-02-05 00:51:15

标签: javascript

我正在尝试(也许是徒劳)想出一种方法来使用发布 - 订阅模式,而 a)使用 no 库和 b )最小化使用它的模块中的样板代码。到目前为止,我提出的最好的是:

var handle = document.createElement();
var unsubscribe = AwesomeModule.subscribe(handle);

handle.addEventListener('awesome', function() {
    console.log('awesome');
});

这将非常有效,除了使用AwesomeModule的人可能会因为必须提供一个未用作元素的随机DOM元素而感到困惑。

我尝试了以下操作并且效果不佳:

var handle = Object.create(EventTarget);
var unsubscribe = AwesomeModule.subscribe(handle);

handle.addEventListener('awesome', function(){
    console.log('awesome')
});

我得到TypeError: Object [object Object] has no method 'addEventListener'。有趣的是,即使handle将EventTarget作为其原型,它似乎也没有在原型链中查找。

为什么这不起作用?有没有办法用纯JS实现EventTarget?它可以在一行代码中完成,不会让AwesomeModule的用户感到恐惧吗?

编辑:我不知道为什么昨晚我没有发生这种情况,但我认为EventTarget是一个接口意味着它没有实现代码。令人困惑的是,在Chrome调试器控制台Object.create(EventTarget)中,出现的对象使addEventListener成为原型链。也许是在说谎。谁能解释这种行为?谁能解释为什么W3选择不让EventTarget成为一个具体的“类”?

3 个答案:

答案 0 :(得分:2)

看起来我原来问题的答案是肯定的。由于JavaScript没有像Java那样对合法实现进行编译时检查的继承模型,我想任何Object只能通过具有相同名称的方法来实现接口。但是,这样做会构成一个库,因为addEventListener代码没有在EventTarget中实现(我以前认为它是)。由于似乎没有跨浏览器方式来获取vanilla EventTarget,我可能会将window.addEventListener与自定义事件结合使用。

答案 1 :(得分:1)

答案 2 :(得分:1)

这是一组效果很好的简单例程。 与a small polyfill for IE9 and 10一起,支持是体面的。

你可以根据需要将这些功能合并到你的项目中,我认为它不构成一个库,或者我不会发布它。

var on = addEventListener.bind(window),
 off = removeEventListener.bind(window),
 emit = function(name, val) {
    dispatchEvent(new CustomEvent(name, {
        detail: val
    }));
};



// demo:
on("test", function(e){ alert(e.detail);});
emit("test", "Number is " + Math.random());

我不认为它可以在不牺牲速度或库兼容性的情况下变得更简单(~180个字符)。