Как ссылаться на объект вызывающего абонента ("this") с помощью attachEvent
Используя метод .attachEvent()
в IE, как я могу ссылаться на объект вызывающего объекта (элемент, вызвавший событие) с помощью this
? В обычных браузерах, используя .addEventListener
, var this
указывает на элемент, тогда как в IE он указывает на объект window
.
Мне нужно, чтобы он работал со следующим кодом:
var element = //the element, doesn't matter how it is obtained
element.addAnEvent = function(name, funct){
if(element.addEventListener) // Works in NORMAL browsers...
else if(element.attachEvent){
element.attachEvent("on"+name, funct);
//where the value of "this" in funct should point to "element"
}
}
Я только что сделал этот код, это не совсем то же самое, что и мой код, но если он сработает с ним, он работает со мной!
Ответы
Ответ 1
Из эта статья об атрибутах quirksmode в отношении attachEvent
:
- События всегда пузырятся, нет возможности захвата.
- Функция обработки событий ссылается, а не копируется, , поэтому это ключевое слово всегда ссылается на окно и абсолютно бесполезно.
Результатом этих двух недостатков является то, что когда событие пузырится, невозможно знать, какой элемент HTML в данный момент обрабатывает событие. Я более подробно объясню эту проблему на странице заказа события.
Так как модель добавления событий Microsoft поддерживается только с помощью проводника 5 и выше в Windows, ее нельзя использовать для кросс-браузерных скриптов. Но даже для приложений Explorer-on-Windows лучше всего не использовать его, так как проблема пузырирования может быть довольно неприятной в сложных приложениях.
Я не тестировал его, но возможное обходное решение может заключаться в том, чтобы обернуть обработчик анонимной функцией, которая вызывает ваш обработчик через funct.call()
.
else if(element.attachEvent){
element.attachEvent("on"+name, function(){ funct.call( element ) });
}
Приношу свои извинения за непроверенное решение. Мне не нравится это делать, но сейчас я не могу легко добраться до IE.
Ответ 2
Если вы находитесь в IE, вы можете получить объект "вызывающего", как вы его называете, путем доступа к window.event.srcElement
в функции обработчика событий. Этот объект обычно упоминается как цель или источник события.
var funct = function(event) {
if ( !event ) {
event = window.event;
}
var callerElement = event.target || event.srcElement;
// Do stuff
};
Этот код не проверен, но должен отключить его в правильном направлении.
Ответ 3
Привяжите его. Ну, вы не можете использовать Function.prototype.bind
, который добавляется в javascript 1.8.5, но вы можете использовать закрытие и Function.prototype.apply
.
var element = //the element, doesn't matter how it is obtained
element.addAnEvent = function(name, funct){
if(element.addEventListener) // Works in NORMAL browsers...
//...
else if(element.attachEvent){
element.attachEvent("on"+name, function() {
//call funct with 'this' == 'element'
return funct.apply(element, arguments);
});
}
}
Ответ 4
Я думаю, было бы лучше расширить Element
объект через цепочку прототипов вместо добавления вашего метода к каждому элементу, который вы хотите добавить события (работает со всеми браузерами)..
Element.prototype.addAnEvent = function(name, funct){
if(this.addEventListener) // Works in NORMAL browsers...
{
this.addEventListener(name,funct, false);
}
else if(this.attachEvent){
var _this = this;
this.attachEvent("on"+name, function(){funct.apply(_this);});
//where the value of "this" in funct should point to "element"
}
};
Таким образом, он будет работать для всех ваших текущих и будущих элементов (и вам нужно только запустить его один раз).