Reputation: 30272
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
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
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
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
Upvotes: 2
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