Ошибка переопределения элемента addEventListener в Firefox
Я пытаюсь переопределить объект Element addEventListener
метод, в кросс-браузерной манере. Цель состоит в том, чтобы я мог загружать некоторые сторонние сценарии асинхронно, и эти сценарии вызывают этот метод преждевременно.
Я создал HTML-файл, который отлично работает в Chrome, но в Firefox я получаю следующее исключение:
"Недопустимая операция с объектом-прототипом WrappedNative" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"
Если вы закомментируете строки в файле, которые изменяют методы INSTANCE, это работает. Но мне нужно сделать это на "типе класса" (то есть прототипе).
Мы ценим любые предложения.
Спасибо, Гайпо
Вот файл, который я создал
<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>
2 ответа
Как говорит Марсель, это связано с тем, как выставляются хост-объекты. Проблема в том, что если вы переопределяете предопределенное свойство интерфейса, оно не изменяется в интерфейсах, которые наследуют от него (по крайней мере, в Firefox).
Хотя я согласен с замечаниями Марселя, на самом деле есть способ сделать это. Вы должны переопределить свойство минимально возможного интерфейса объекта, для которого вы хотите сделать это. В вашем случае это будет HTMLImageElement
,
Это сделает свое дело:
(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);
}
})();
Пожалуйста, используйте действительный Doctype, предпочтительно тот, который переводит браузеры в режим (почти) стандартов (
<!DOCTYPE html>
Это хорошо).typeof
это оператор, вам не нужны скобки (но это не больно)Самое главное: не пытайтесь манипулировать DOM
Element
"sprototype
это хост-объекты, и вы не можете полагаться на хост-объекты, раскрывающие какие-либо основные функциональные возможности JavaScript объекта. Хуже того, может быть снижение производительности, и вы можете сломать другие вещи. Держитесь подальше от этой техники. Для получения дополнительной информации прочитайте Что не так с расширением DOM.
Чего вы хотите добиться, чтобы ваши слушатели событий вызывались автоматически при использовании сторонних сценариев?