开发者

Firefox add-on - `this` works in one method but fails in another method of the same object

I am developing an add-on for Firefox (3.6.*). in the following code notify called from inside init works fine, but I get an error saying this.notify is not a function when it is called from within onPageLoad. Why is that?

Also when I change the call to myextobj.notify('title', 'msg'), it works. The same is true for accessing variables. So, what is the difference between this and the object name as a prefix?

var myextobj = {
  init: functi开发者_运维技巧on() {
    this.notify('init', 'We are inside init');
    ...
    var appcontent = document.getElementById("appcontent");   // browser  
    if(appcontent)  
      appcontent.addEventListener("DOMContentLoaded", this.onPageLoad, true);
  },
  onPageLoad: function(aEvent) {
    this.notify('onPageLoad', 'We are inside onPageLoad');
    ...
  },

  notify: function (title, text) {  
    Components.classes['@mozilla.org/alerts-service;1'].  
      getService(Components.interfaces.nsIAlertsService).  
      showAlertNotification(null, title, text, false, '', null);  
  }  
};
window.addEventListener("load", function() { myextobj.init(); }, false);


When you do this:

appcontent.addEventListener("DOMContentLoaded", this.onPageLoad, true);

you just add the function that is hold in onPageLoad as event handler. The connection to the object is lost and this will refer to the global object when executed.

Just create an anonymous function as you do for the load event:

var that = this; // capture reference to object
appcontent.addEventListener("DOMContentLoaded", function(event) {
    that.onPageLoad(event);
    // myextobj.onPageLoad(event); should also work in this case
}, true);

Remember that functions are first class objects in JavaScript, they can be passed around like any other value. Functions have no reference to an object they are defined on, because they don't belong to that object. They are just another kind of data.

To which object this refers to in a function is decided upon execution and depends on the context the function is executed in. If you call obj.func() then the context is obj, but if you assign the function to another variable before like var a = obj.func (that is wat you do with adding the event handler (in a way)) and then call a(), this will refer to the global object (which is window most of the time).


When onPageLoad is called for the event, 'this' would not be referring to your myextobj. Because it wasn't called in the context of your object myextobj.

The way I deal with this is, by having all member functions of an object using the following convention.

var myObj = {
   .....
   counter: 0,
   .....
   myFunction: function () {
     var t = myObj;
     t.myOtherFunc();
   },

   ....
   myOtherFunc: function() {
     var t = myObj;
     t.counter++;
   }
};

See how, I'm aliasing myObj as t, to save on typing and making my intent of using this clear.

Now you can call your methods safely from any context without worrying about what this would be referring to. Unless you really want the standard behavior; in that case, you may like to look at the call and apply methods. This link might help: Function.apply and Function.call in JavaScript

  • You may also want to look at a recent addition to JavaScript (would be available in FireFox 4): the bind method: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

  • Another link, which directly addresses your problem: https://developer.mozilla.org/en/DOM/element.addEventListener#The_value_of_this_within_the_handler


The other way to add an event listener without losing track of this is to pass this itself as the event listener. However you are limited in that the function is always called handleEvent, so it's less useful if you have many listeners (unless they are all for different events, in which case you can switch on the event's type).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜