Safari 中的 EventTarget 接口

EventTarget interface in safari

我开始通过添加一些有用的 prototypes 来扩展 EventTarget 界面,但后来我在 Safari 8 上对其进行了测试并得到:

[Error] ReferenceError: Can't find variable: EventTarget

我在 MDN 上发现 "window.EventTarget 对于 Safari 不存在"

This question 看起来很有趣,但它是关于 IE8 的。

所以,我想知道是否可以在 Safari 上访问对 EventTarget 接口的引用,或者使用像 EventTarget.prototype.hasEventListener 和 [=14= 这样的代码的解决方法] 在 Safari 上没有出现任何错误?

编辑 我发现了一个有趣的 commit,它说它是在 2015 年 9 月 12 日实现的(从时间戳开始),但它肯定在 Safari 9.1

中不起作用

解决方法:

我只是使用 Element interface 作为 Safari 的后备

var EventTarget = EventTarget || Element;
EventTarget.prototype.addEventListener = function(){/*Some magic here*/};

我还检查了 Element 从 EventTarget 接口继承了 prototypes,确实如此! (document.body.addEventListener == EventTarget.prototype.addEventListener 返回 true

Safari 不允许您在自己的对象中使用 DOM 元素以外的 EventTarget 界面。所以我简单地复制了 class 来做到这一点。

class EventDispatcher {

    constructor() {
        this._listeners = [];
    }

    hasEventListener(type, listener) {
        return this._listeners.some(item => item.type === type && item.listener === listener);
    }

    addEventListener(type, listener) {
        if (!this.hasEventListener(type, listener)) {
            this._listeners.push({type, listener, options: {once: false}});
        }
        // console.log(`${this}-listeners:`,this._listeners);
        return this
    }

    removeEventListener(type, listener) {
        let index = this._listeners.findIndex(item => item.type === type && item.listener === listener);
        if (index >= 0) this._listeners.splice(index, 1);
//        console.log(`${this}-listeners:`, this._listeners);
        return this;
    }

    removeEventListeners() {
        this._listeners = [];
        return this;
    }

    dispatchEvent(evt) {
        this._listeners
            .filter(item => item.type === evt.type)
            .forEach(item => {
                const {type, listener, options: {once}} = item;
                listener.call(this, evt);
                if (once === true) this.removeEventListener(type, listener)
            });
        // console.log(`${this}-listeners:`,this._listeners);
        return this
    }
}