最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

oop - Object oriented Javascript: event handling - Stack Overflow

programmeradmin1浏览0评论

I'm trying to create an event for an object to have it listen to it. Consider the following example:

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

I'm expecting to receive an output like:

Spot: Awooooooof Woof!

Dot: Awooooooof Woof!

But what I get is:

undefined: Awooooooof Woof!

What is wrong with my example? How can I register a listener that every instance of Dog has?

I'm trying to create an event for an object to have it listen to it. Consider the following example:

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

I'm expecting to receive an output like:

Spot: Awooooooof Woof!

Dot: Awooooooof Woof!

But what I get is:

undefined: Awooooooof Woof!

What is wrong with my example? How can I register a listener that every instance of Dog has?

Share Improve this question edited Jul 23, 2020 at 20:40 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Mar 12, 2013 at 8:59 Alessandro CappelloAlessandro Cappello 5288 silver badges25 bronze badges 0
Add a comment  | 

3 Answers 3

Reset to default 10

In this line

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

you don't bind the scope of this.bark to this. In JavaScript, the value of this does not depend on where the function is defined but from where it is called. This means when you pass this.bark to addEventListener you detach it from the current object.

In frameworks like prototype.js and JQuery there are shortcuts for binding this, with vanilla JavaScript you can do it like this:

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

And then:

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

The problem you have is that this inside the function does not refer to the object you want to manipulate.

How about adding the function bark inside the function definition?

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

The Problem

The this keyword, inside Dog.prototype.bark() points to the object that invoked the method. For example, when spot.bark() is called, this.name evaluates to spot.name, like so:

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

When the event listener is added inside Dog's constructor, the document object is told to listen for that event, and told to call Dog.prototype.bark() when it hears that event. This setup is done correctly and the document object will call the correct function when it hears that event,

The trouble happens later when the document object actually calls the bark function. Now, this points to the document object, and this.name evaluates to document.name, like so:

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

document.name doesn't exist and that's why the output is: undefined: Awooooooof Woof!

The Fix

Use Function.prototype.bind() to bind the provided value to a function's this keyword, like so:

document.addEventListener("Moon", this.bark.bind(this), false);
发布评论

评论列表(0)

  1. 暂无评论