Skip to content Skip to sidebar Skip to footer

Having The Correct Value Of 'this' In Js

I have two Javascript 'objects' similar to so.... var Object2 = new (function() { this.FetchData = function(callback) { // do some stuff callback(data); };

Solution 1:

A technique commonly used in frameworks is to let the caller decide on what the this context should be for the callback function. So the FetchData function looks like (thanks to @Andy for telling me about the default scope when context is null or undefined - it is the global object),

this.FetchData = function(callback, context) {
    callback.call(context, data);
};

When calling FetchData, pass Object1 as the context for the callback,

Object2.FetchData(this.OnData, this);

Another option is to bind the OnData function with Object1 using Function.prototype.bind

Object2.FetchData(this.onData.bind(this));

Solution 2:

The simple way of doing it is storing a reference to this in a variable, then using the call() method:

this.LoadData = function() {
    varself = this;
    Object2.FetchData(function () { self.OnData.call(self) });
};

If you're doing this a lot, you might want to consider using the .bind() method on the function prototype in ECMAScript 5th edition. This method can be implemented where unsupported:

// From Prototype.jsif (!Function.prototype.bind) { // check if native implementation availableFunction.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    returnfunction(){ 
      return fn.apply(object, 
        args.concat(Array.prototype.slice.call(arguments))); 
    }; 
  };
}

And the resulting function call:

this.LoadData = function() {
    Object2.FetchData(this.OnData.bind(this));
};

PrototypeJS - bind()

Solution 3:

The basic solution is to force context on the callback with apply. (Or call. The difference is how parameters are passed. Either an array or 'normally') See the MDC for documentation.

Solution 4:

For a callback, you're stuck with 'this' being the window (usually). However, you could add a member to Object1 that points to itself (a lot of times it's gets call 'self', i.e. "var self = this;"), and then use that, i.e. self.DisplayStuff().

Solution 5:

The ambiguity of "this" is really annoying to me with javascript. So I just avoid "this" as much as possible. I do it this way:

var Object2 = (function() { // no need for a "new" keyword any morevarself = {}; // instead of the auto-supplied "this", create my own "self"self.FetchData = function(callback) {
        // do some stuff
        callback(data);
    };
    returnself; // don't forget to return "self"
});

var Object1 = (function() {

    varself = {}; // instead of the auto-supplied "this", create my own "self"self.DisplayStuff = function() {

    };

    self.LoadData = function() {
        Object2.FetchData(this.OnData);
    };

    self.OnData = function(data) {
        self.DisplayStuff();
    };

    returnself; // don't forget to return "self"

});

You lose the ability to use Object.prototype with this technique, you lose the ability to test using "instanceof", but you never have to think about what "this" is.

Post a Comment for "Having The Correct Value Of 'this' In Js"