覆盖事件属性

时间:2013-08-02 21:57:50

标签: javascript performance

如何覆盖事件属性?我这样做的原因是因为我想在鼠标事件上覆盖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);

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:2)

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

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