views:

529

answers:

4

I have a problem with an object I have created that looks something like this:

var myObject = {

    AddChildRowEvents: function(row, p2) {
        if(document.attachEvent) {
            row.attachEvent('onclick', function(){this.DoSomething();});
        } else {
            row.addEventListener('click', function(){this.DoSomething();}, false);
        }
    },

    DoSomething: function() {
        this.SomethingElse(); //<-- Error here, object 'this' does not support this method.
    }
}

The problem is that when I am inside the 'DoSomething' function, 'this' does not refer to 'myObject' what am I doing wrong?

A: 

I'm not sure what the generic solution is, but Prototype solves this using the bindAsEventListener function. You could either use Prototype, or look at how they implement it.

rmeador
+10  A: 

WHen the function is called, "this" refers to row. If you want to have the object, you can do it something like this: ]

AddChildRowEvents: function(row, p2) {
    var theObj = this;
    if(document.attachEvent) {
         row.attachEvent('onclick', function(){theObj.DoSomething();});
    } else {
         row.addEventListener('click', function(){theObj.DoSomething();}, false);
    }
},

When the function is called, it has access to the variable theOBj which was in scope when the function was defined.

Mike Kantor
took me a while to get it - the reason is that row.attachEvent attaches an event to the row, and when that event fires, the row is the one that calls the function (it likely does something like f.apply(this, args)). am i correct?
Claudiu
Yes, that's correct.
Mike Kantor
A: 

This is a common issue with closures. To resolve it try something like this:

var myObject = {    
    AddChildRowEvents: function(row, p2) { 
        var self = this;

        if(document.attachEvent) {            
             row.attachEvent('onclick', function(){this.DoSomething(self);});        
        } else {            
             row.addEventListener('click', function(){this.DoSomething(self);}, false);        
        }    
    },    

    DoSomething: function(self) {       
        self.SomethingElse(); 
    }
}
+2  A: 

this always refers to the inner function, if you have nested functions, you have to create another variable and point that to this.

var myObject = {
    that = this;
    AddChildRowEvents: function(row, p2) {
        if(document.attachEvent) {
            row.attachEvent('onclick', function(){that.DoSomething();});
        } else {
            row.addEventListener('click', function(){that.DoSomething();}, false);
        }
    },

    DoSomething: function() {
        that.SomethingElse();
    }
}
svinto