简体   繁体   English

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

[英]Is There a Way to Implement EventTarget with Plain JS?

I'm trying (perhaps in vain) to come up with a way to use the publish-subscribe pattern while a) using no libraries and b) minimizing boilerplate code in modules that use it. 我想(也许是徒劳的)想出一个方法,可使用发布-订阅模式使用库,而a)b)在使用它的模块最大限度地减少样板代码。 So far the best I've come up with is this: 到目前为止,我提出的最好的是:

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

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

This will work pretty well, except that people using AwesomeModule might be confused by having to provide a random DOM element that isn't used as an element. 这将非常有效,除了使用AwesomeModule的人可能会因为必须提供未用作元素的随机DOM元素而感到困惑。

I tried the following and it doesn't work too well: 我尝试了以下内容并且效果不佳:

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

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

I get TypeError: Object [object Object] has no method 'addEventListener' . 我得到TypeError: Object [object Object] has no method 'addEventListener' Interestingly enough, it doesn't seem to look in the prototype chain even though handle has EventTarget as its prototype. 有趣的是,即使handle将EventTarget作为其原型,它似乎也没有在原型链中查找。

Why doesn't this work? 为什么这不起作用? Is there a way implement EventTarget with pure JS? 有没有办法用纯JS实现EventTarget? Can it be done in a single line of code that won't horrify users of AwesomeModule? 它可以在一行代码中完成,不会让AwesomeModule的用户感到恐惧吗?

EDIT: I don't know why it didn't occur to me last night, but I suppose EventTarget being an interface means that it doesn't have implemented code. 编辑:我不知道为什么昨晚我没有发生,但我认为EventTarget是一个接口意味着它没有实现代码。 What's confusing is that in the Chrome debugger console Object.create(EventTarget) makes an object that appears to have addEventListener in is prototype chain. 令人困惑的是,在Chrome调试器控制台中, Object.create(EventTarget)使得一个看似具有addEventListener的对象是原型链。 Maybe its lying. 也许是在说谎。 Can anyone explain this behavior? 谁能解释这种行为? Can anyone explain why W3 chose not to make EventTarget a concrete "class"? 任何人都可以解释为什么W3选择不让EventTarget成为一个具体的“类”?

It looks like the answer to my original question is "yes." 看起来我原来问题的答案是肯定的。 Since JavaScript doesn't have an inheritance model like Java which does compile-time checks for legal implementation, I suppose any Object can implement an interface merely by having methods with the same name. 由于JavaScript没有像Java那样对合法实现进行编译时检查的继承模型,我想任何Object只能通过具有相同名称的方法来实现接口。 However, doing this would constitute making a library since the addEventListener code isn't implemented in EventTarget (I had previously assumed it was). 但是,这样做会构成一个库,因为addEventListener代码没有在EventTarget中实现(我以前认为它是)。 Since there seems to be no cross-browser way to get a vanilla EventTarget, I will probably use window.addEventListener in conjunction with custom events. 由于似乎没有跨浏览器方式来获取vanilla EventTarget,我可能会将window.addEventListener与自定义事件结合使用。

Here's a simple set of routines that works well. 这是一组运行良好的简单例程。 with a small polyfill for IE9 and 10 , support is decent. 对于IE9和10的小型polyfill ,支持是体面的。

you can incorporate these functions into your project as needed, i don't think it constitutes a library, or i wouldn't post this. 你可以根据需要将这些功能合并到你的项目中,我不认为它构成了一个库,或者我不会发布这个。

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());

i don't think it can get much simpler (~180 chars) without sacrificing speed or library compatibility. 在不牺牲速度或库兼容性的情况下,我认为它不会变得更简单(~180个字符)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM