2013-08-02 108 views
0

如何覆蓋事件屬性?我這樣做的原因是因爲我想在鼠標事件上覆蓋像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); 
+1

只讀是按規格,你需要的,如果要忽略可能的干將使用'defineProperty'繼承,setter方法並且對原型中的同名命名屬性是隻讀的。 – Esailija

+0

非常感謝您的支持!我仍然需要做一些測試來找出哪些是最高性能的方式,但是這有助於ALOT。 :) –

回答

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

我其實也得出了同樣的結論。至少jQuery和YUI或多或少地這樣做。謝謝你的建議! :) –

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); 
+0

謝謝!我測試了這一點,它似乎比每次創建新的構造函數都快一點。 :) –

+1

@MattiMehtonen但這不是一個公平的測試,因爲你可以通過靜態地使用'document.createEvent(「MouseEvents」)''中的原型,輕鬆地將構造器移出運行時代碼。示例http://jsfiddle.net/mtjhm/ – Esailija

+0

@MattiMehtonen這裏是更好的例子,如果你不檢索任何屬性,應該執行最好的例子,因爲它們是通過getter懶洋洋地檢索的http://jsfiddle.net/mtjhm/1/ – Esailija