2013-03-12 5 views
9

Я пытаюсь создать событие для объекта, чтобы он его прослушивал. Рассмотрим следующий пример:Объектно-ориентированный Javascript: обработка событий

var moon; 

moon = document.createEvent("Event"); 
moon.initEvent("Event",true,true); 

var Dog = function (name) { 
    this.name = name; 

    document.addEventListener("Event",this.bark,false); 
}; 
dog.prototype.bark = function() { 
    console.log(this.name + ': Awooooooof Woof!'); 
}; 


var spot = new Dog("Spot"); 
var dot = new Dog("Dot"); 


//invoke 
document.dispatchEvent(moon); 

Я ожидал получить выход вроде:

Spot: Awooooooof Woof! 

Dot: Awooooooof Woof! 

Но то, что я получаю:

undefined: Awooooooof Woof! 

Что случилось с моим примером? Как я могу зарегистрировать слушателя, что у каждого экземпляра собаки? Спасибо заранее!

ответ

9

В этой строке

document.addEventListener("Event",this.bark,false); 

не связывают сферу this.bark к this. В JavaScript значение this не зависит от того, где определена функция, но откуда она вызывается. Это означает, что при переходе this.bark на addEventListener вы отсоединяете его от текущего объекта.

В рамках как prototype.js и JQuery имеются ярлыки для связывания this, с ванильным JavaScript вы можете сделать это следующим образом:

function bind(scope, fn) { 
    return function() { 
     return fn.apply(scope, arguments); 
    } 
} 

И потом:

document.addEventListener("Event",bind(this, this.bark),false); 
+0

Большое спасибо! Я понял, как добиться этого с помощью jQuery, но я думаю, что ваше решение более элегантно. – Alessandro

4

Проблема заключается в том, что внутри функции функция не относится к объекту, который вы хотите манипулировать.

Как насчет добавления функции bark внутри определения функции?

var Dog = function (name) { 
    this.name = name;  
    this.bark = function() { 
     console.log(name + ': Awooooooof Woof!'); 
    }; 
    document.addEventListener("Event", this.bark, false); 
}; 
0

Проблему

Ключевое слово this, внутри Dog.prototype.bark() точки t o объект, вызывающий метод. Например, когда spot.bark() называется, this.name вычисляет spot.name, например, так:

Dog.prototype.bark = function() { 
    console.log(spot.name + ': Awooooooof Woof!'); 
}; 

Когда добавляется прослушиватель событий внутри конструктора собаки, объект document сказал, чтобы слушать для этого события, и сказал, чтобы позвонить Dog.prototype.bark() когда он слышит это событие. Эта настройка выполнена правильно, и объект document вызовет правильную функцию, когда он услышит это событие,

Неполадка возникает позже, когда объект document фактически вызывает функцию коры.Теперь, this указывает на document объекта и this.name вычисляет document.name, например, так:

Dog.prototype.bark = function() { 
    console.log(document.name + ': Awooooooof Woof!'); 
}; 

document.name не существует, и поэтому выход: undefined: Awooooooof Woof!

Исправление

Используйте Function.prototype.bind(), чтобы связать предоставленное значение с ключевым словом this, например:

document.addEventListener("Moon", this.bark.bind(this), false); 
Смежные вопросы