简体   繁体   English

无法在Firefox中覆盖Element的addEventListener

[英]Failure to override Element's addEventListener in Firefox

I'm trying to override the Element object's addEventListener method, in a cross-browser manner. 我正在尝试以跨浏览器的方式覆盖Element对象的addEventListener方法。 The purpose is so that I can load some 3rd party scripts asynchronously, and those scripts call this method prematurely. 目的是使我可以异步加载一些第三方脚本,而这些脚本会过早调用此方法。

I created an HTML file that works perfectly in Chrome, but on Firefox I get this exception: 我创建了一个可以在Chrome浏览器中完美运行的HTML文件,但是在Firefox上却遇到了以下异常:

"Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" nsresult:“对WrappedNative原型对象的非法操作”:“ 0x8057000c(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)”

If you comment out the lines in the file that change the INSTANCE methods, it works. 如果注释掉文件中更改INSTANCE方法的行,则它可以工作。 But I need to do it on the "class type" (ie prototype). 但是我需要对“类类型”(即原型)进行操作。

Any suggestions would be appreciated. 任何建议,将不胜感激。

Thanks, Guypo 谢谢Guypo

Here's the file I created 这是我创建的文件

<html><body>
<img id="testImg" src="http://www.blaze.io/wp-content/themes/Blaze/images/header_logoB.png">
<script>
function myLog(msg) { "undefined" != typeof(console) && console.log("Log: " + msg); }
function customListener(type, event, useCapture) {
  // Register the event
  myLog('Registering event');
  this._origListener.apply(this, arguments);
}
// Also tried HTMLImageElement
Element.prototype._origListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = customListener;

var img = document.getElementById("testImg");
// Uncommenting these lines works - but in the real case I can't access these objects
//img._origListener = img.addEventListener;
//img.addEventListener = customListener;
img.addEventListener('load',function() { myLog('load callback'); }, false);

</script>
</body>
</html>

Like Marcel says, this has to do with the way host objects are exposed. 就像Marcel所说的那样,这与宿主对象的公开方式有关。 The problem is that if you override a predefined property of an interface, it doesn't get changed in the interfaces that inherit from it (at least in Firefox). 问题在于,如果您重写接口的预定义属性,则在继承自该接口的接口中(至少在Firefox中)该属性不会更改。

Although I agree with Marcel's remarks, there is in fact a way to do this. 虽然我与马塞尔的言论一致,其实也办法做到这一点。 You should override the property of the lowest possible interface of the object you want to do this for. 您应该覆盖要执行此操作的对象的最低接口的属性。 In your case this would be the HTMLImageElement . 在您的情况下,这将是HTMLImageElement

This will do the trick: 这将达到目的:

(function() {
    var _interfaces = [ HTMLDivElement, HTMLImageElement /* ... (add as many as needed) */ ];
    for (var i = 0; i < _interfaces.length; i++) {
        (function(original) {
            _interfaces[i].prototype.addEventListener = function(type, listener, useCapture) {

                // DO SOMETHING HERE

                return original.apply(this, arguments);
            }
        })(_interfaces[i].prototype.addEventListener);
    }
})();
  1. Please use a valid Doctype, preferably one that cast browsers into (Almost) Standards mode ( <!DOCTYPE html> is fine). 请使用有效的Doctype,最好是将浏览器转换为(几乎)标准模式的<!DOCTYPE html><!DOCTYPE html>可以)。

  2. typeof is an operator, you don't need the parentheses (but it doesn't hurt) typeof是一个运算符,您不需要括号(但不会造成伤害)

  3. Most important: don't try to manipulate DOM Element 's prototype : those are host objects and you can't rely on host objects exposing any of the core JavaScript functionality of an object. 最重要的是: 不要尝试操作DOM Elementprototype :它们是宿主对象,您不能依赖宿主对象来公开对象的任何核心JavaScript功能。 Worse, there may be a performance penalty and you might break other things. 更糟糕的是,这可能会降低性能,并且您可能会破坏其他东西。 Stay away from that technique. 远离该技术。 For more information, read What's wrong with extending the DOM . 有关更多信息,请阅读扩展DOM有什么问题

What is it that you want to achieve, that you want your event listeners to be called automatically when using 3rd party scripts? 您想要实现什么,并且希望在使用第三方脚本时自动调用事件侦听器?

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

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