1

如何覆盖事件属性?我这样做的原因是因为我想覆盖pageX鼠标事件等属性,并且该属性是只读的。

我第一次尝试这个

context.addEventListener(type, function (e) {
    var Event;

    Event = function () {

        this.pageX = pageX;
        this.pageY = pageY;

        this.preventDefault = function () {
            e.preventDefault();
        };

        this.stopPropagation = function () {
            e.stopPropagation();
        };

        this.stopImmediatePropagation = function () {
            e.stopImmediatePropagation();
        };
    };

    Event.prototype = e;

    callback.call(context, new Event());
}, false);

不幸的是,这太好了,令人难以置信。它不适用于某些浏览器(至少 Chrome)。pageX无法设置属性,因为只读状态以某种方式从事件对象继承。

然后我尝试了

context.addEventListener(type, function (e) {
    var evt = {},
        i;

    for (i in e) {
        if (e.hasOwnProperty(i)) {
            evt[i] = e[i];
        }
    }

    evt.pageX = pageX;
    evt.pageY = pageY;

    evt.preventDefault = function () {
        e.preventDefault();
    };

    evt.stopPropagation = function () {
        e.stopPropagation();
    };

    evt.stopImmediatePropagation = function () {
        e.stopImmediatePropagation();
    };

    callback.call(context, evt);
}, false);

这个可行,但比第一种方法慢约 100 倍。我真的不想走这条路,否则每次使用它都会感到难过。

我考虑过放弃。我可以像pointX原始事件一样添加属性并增加pageX那里的价值。再说一次,如果某些浏览器决定添加属性pointX并将其设为只读,我的所有代码都会被破坏。

任何建议都将受到欢迎。

更新:感谢 Esailija,现在它可以工作了!我在下面添加解决方案。

document.body.addEventListener('mousedown', function (e) {
    var Event = function () {};

    Event.prototype = e;

    Event = new Event();

    Object.defineProperty(Event, 'pageX', {
        value: 999
    });

    console.log(Event);

}, false);
4

2 回答 2

3

无法设置属性 pageX,因为只读状态以某种方式从事件对象继承。

您可以使用 否决该分配行为Object.defineProperty

而不是自定义的,只使用一次的构造函数,你应该去Object.create. 它甚至还有第二个参数defineProperties,所以你可以将你的代码缩短为

context.addEventListener(type, function (e) {
    callback.call(context, Object.create(e, {
        pageX: {value: pageX /* configurable, enumerable, writable? */},
        pageY: {value: pageY /* configurable, enumerable, writable? */}
    }));
    // I'd guess you don't even need the explicit "super" calls
    // for preventDefault, stopPropagation and stopImmediatePropagation
}, false);
于 2013-08-03T14:55:28.247 回答
1

我没有看到从头开始创建一个新的类/函数的好处,每个事件都会被触发。您可以简单地编写一个包装类。

http://jsfiddle.net/F6Urw/1/

document.getElementById('button')
    .addEventListener('click', click);

function click(e) {
    var wrapper = new EventWrapper(e);
    console.log(wrapper.pointX);
    console.log(wrapper.pointY);
}

function EventWrapper(event) {
    this.pointX = event.pageX;
    this.pointY = event.pageY;
    this.originalEvent = event;
}
于 2013-08-02T23:07:54.760 回答