Majid Fouladpour
Majid Fouladpour

Reputation: 30272

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: function() {
    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);

Upvotes: 2

Views: 154

Answers (3)

Neil
Neil

Reputation: 55402

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

Upvotes: 0

xk0der
xk0der

Reputation: 3690

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

Upvotes: 2

Felix Kling
Felix Kling

Reputation: 817010

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

Upvotes: 2

Related Questions