Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

'this' in JavaScript

4.83/5 (4 votes)
12 Aug 2014CPOL4 min read 12K  
How does 'this' in JavaScript differ from 'this' in other languages?

Few people learn JavaScript as a first programming language. Typically, people will start with an object-oriented language such as C#, Java or C++. These languages have a few things in common, such as curly braces, objects, functions, if-statements and loops. Another common feature of object-oriented programming languages is the ‘this’ keyword. It refers to the class which contains the currently executing code.

It can be something of a surprise then when a programmer moves on to JavaScript and discovers that the value returned by ‘this’ is less predictable than expected.

There are five different cases where you might use ‘this’. These include using it in the global namespace, and four different ways of using it inside a function, as described by Douglas Crockford in JavaScript – The Good Parts.

‘this’ in the Global Namespace

In the global namespace, that is, outside of any function, ‘this’ refers to the window object. I don’t see any reason why anyone would want to use ‘this’ in the global namespace, in fact it’s probably a bad idea, nevertheless it can be done and so is worth mentioning for completeness.

Scenario 1 – Method Invocation

In JavaScript (and many other languages), a method is a function which is declared inside of a class or object. Referring to ‘this’ inside of a method refers to the containing object. Therefore in the example below, we are alerted with ‘Roberto Martinez’ rather than ‘Howard Kendall’.

JavaScript
// Set global variable
var manager = 'Howard Kendall';

// 1. Method Invocation
var everton = 
    {
        yearFounded : 1878,
        inEurope : true,
        manager : 'Roberto Martinez',
        getManager : function()
        {
            return this.manager;
        }
    };

alert(everton.getManager()); // alerts 'Roberto Martinez'

This is the kind of behavior you would expect coming from an object-oriented background, so no unpleasant surprises here.

Scenario 2 – Function Invocation

Here we are referring to any function which is not declared inside an object. That is, any function which is declared in the global namespace. Using ‘this’ inside such functions actually refers to the global namespace, rather than the containing function. Strange behaviour indeed, and Douglas Crockford actually describes this behaviour as a mistake by the creators of JavaScript. Thus in the example below, we are alerted with ‘Howard Kendall’, rather than ‘Roberto Martinez’.

JavaScript
// Set global variable
var manager = 'Howard Kendall';

// 2. Function Invocation
var getManager = function()
{
    var manager = 'Roberto Martinez';
    return this.manager;    
};

alert(getManager()); // alerts 'Howard Kendall'

So we have established that ‘this’ inside of a method refers to the method’s containing object, and ‘this’ inside of a global function refers to the global namespace. But what is referred to by ‘this’ inside of a function which is declared inside of a method? The answer is – the global namespace, as shown in the example below.

JavaScript
var manager = 'Howard Kendall';

var everton = 
    {
        yearFounded : 1878,
        inEurope : true,
        manager : 'Roberto Martinez',
        getManager : function()
        {            
            var innerFunction = function()
            {
                return this.manager;
            };            
            return innerFunction();
        }
    };

alert(everton.getManager()); // alerts 'Howard Kendall'

This behaviour is slightly surprising. If we want to use an inner function inside of a method, we can get around the problem by assigning ‘this’ to a variable inside the outer method, as shown below with the ‘that’ variable.

JavaScript
var manager = 'Howard Kendall';

var everton = 
    {
        yearFounded : 1878,
        inEurope : true,
        manager : 'Roberto Martinez',
        getManager : function()
        {
            var that = this;
            
            var innerFunction = function()
            {
                return that.manager;
            };
            
            return innerFunction();
        }
    };

alert(everton.getManager()); // alerts 'Roberto Martinez'

Scenario 3 – Constructor Invocation

A third function scenario is that of the constructor function, that is, a function which is invoked with the ‘new’ keyword. When a function is invoked in this way, the ‘this’ keyword refers to the object created, even if the constructor function was defined in the global namespace. Therefore, in the example below, we are alerted first with ‘Howard Kendall’ and then with ‘Joe Royle’. We refer to ‘this’ inside of a global namespace function when we set the ‘manager’ variable inside of ‘getEverton’, but as we call the function with the ‘new’ keyword, the global namespace ‘manager’ variable is not updated.

JavaScript
var manager = 'Howard Kendall';

// 3. Constructor Invocation
var getEverton = function()
{
    this.yearFounded = 1878;
    this.inEurope = true;
    this.manager = 'Joe Royle'; 
    
    this.getManager = function()
    {
        return this.manager;
    };
};

var efc = new getEverton();
alert(manager); // alerts Howard Kendall
alert(efc.getManager()); // alerts Joe Royle

The same behaviour is displayed when we call a method declared on the constructor function’s prototype, and properties can be set on our new object in the normal way.

JavaScript
// 3. Constructor Invocation
var getEverton = function()
{
    this.yearFounded = 1878;
    this.inEurope = true;
    this.manager = 'Joe Royle';    
};

var efc = new getEverton();
getEverton.prototype.getManager = function()
{
    return this.manager;
};
    
alert(efc.getManager()); // alerts 'Joe Royle'

var efc2 = new getEverton();
efc2.manager = 'Harry Catterick';
alert(efc2.getManager()); // alerts 'Harry Catterick'

So to summarize constructor invocation, it reflects typical object-oriented behavior more closely than function invocation. However, it can be dangerous to rely on this approach, as if we forget to use the ‘new’ keyword, our constructor function will be invoked as a regular global function, and we will see the behavior described above in scenario 2.

Scenario 4 – Apply Invocation

Our final function invocation scenario is the apply invocation pattern. The apply method is defined on the function prototype, therefore it can be invoked on any function. This approach to invocation allows us to provide any object we want to represent ‘this’ inside of the function. Its first argument is bound to ‘this’, and its second argument is an optional array of parameters to be passed to the function. Thus in the example below, we are first alerted with ‘Joe Royle’ and then with ‘Harry Catterick’.

JavaScript
var everton = 
    {
        yearFounded : 1878,
        inEurope : true,
        manager : 'Roberto Martinez',
        getManager : function()
        {
            return this.manager;
        }
    };

var getEverton = function()
{
    this.manager = 'Joe Royle';    
};

var efc = new getEverton();
var efc2 = new getEverton();
efc2.manager = 'Harry Catterick';    

// 4. apply() Invocation
alert(everton.getManager.apply(efc)); // alerts 'Joe Royle'
alert(everton.getManager.apply(efc2)); // alerts 'Harry Catterick'

I have attempted here to clearly describe the different behaviors you might see when using the ‘this’ keyword in JavaScript. However, it is a difficult area to describe in plain English. If you find my descriptions confusing, I recommend reading Crockford’s book. All the code examples are available to play with at this jsfiddle.

The post Something Like This appeared first on The Proactive Programmer.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)