Mark Brown
Mark Brown

Reputation: 12544

Prototypal inheritance and the value of 'this'

I'm building an app with several 'modules'. Each module requires a similar base set of functionality, so I have created a base module that each module will inherit from via prototypal inheritance. Some of the function names on the base module are quite long, and since these functions are used often, I would like to assign shorter names within each module, but this causes issues with the value of 'this' setting it equal to DOMWindow.

Please see the code below:

var SAMPLEAPP = SAMPLEAPP || {};

//This is a base module that I want all other modules to inherit from
SAMPLEAPP.Module = function(){

};

SAMPLEAPP.Module.prototype.someLongFunctionName = function(){
    console.log(this);
};


//This is a module that inherits from the base module
SAMPLEAPP.RouterModule= function(){
    var shortName = this.someLongFunctionName;

    //This correctly logs 'SAMPLEAPP.RouterModule', but I would rather not type 
    //out this long function name each time I need to use the function
    this.someLongFunctionName();

    //However, this code logs 'DOMWindow' when I would expect the value of 'this' 
    //to be the same as the direct call to this.someLongFunctionName
    shortName();
};

SAMPLEAPP.RouterModule.prototype = new SAMPLEAPP.Module();


new SAMPLEAPP.RouterModule();

My Question: How can I modify the code so that calling shortName() logs SAMPLEAPP.RouterModule? If possible, I would rather change the way the modules are defined than the actual call to shortName (i.e. shortname.call(this), defeats the purpose of creating an alias for someLongFunctionName)

Upvotes: 2

Views: 89

Answers (4)

Jordan Brown
Jordan Brown

Reputation: 13883

Another solution is to use a binding function to bind a new context to the function.

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

var shortName = this.someLongFunctionName.bind(this);

Upvotes: 1

James Allardice
James Allardice

Reputation: 166071

As others have mentioned, you can use call or apply (either will work, the difference is simply how arguments are passed to the function).

Alternatively, you can use the ES5 bind method, which binds a context to a function (in this case the context will be this):

var shortName = this.someLongFunctionName.bind(this);

You can then call shortName as you normally would:

shortName();

Here's a working example. And here's the most relevant part of the MDN article:

The bind() function creates a new function (a bound function) with the same function body (internal Call attribute in ECMAScript 5 terms) as the function it is being called on (the bound function's target function) with the this value bound to the first argument of bind(), which cannot be overridden.

Upvotes: 2

Scorpion-Prince
Scorpion-Prince

Reputation: 3634

You can pass the "this" context to the method call, by using the call / apply function. In your case it can be either

shortName.apply(this);

OR

shortName.call(this);

Upvotes: 1

sergiogarciadev
sergiogarciadev

Reputation: 2202

You can change the call to shortName(); to shortName.call(this);.

The this is javascript is a bit trick. Is based on context.

Upvotes: 0

Related Questions