What is this in JavaScript?

Knowing what this is at any point in JavaScript is a very common source of confusion for new and experienced JavaScript developers alike. This article attempts to detail what this is and how to think about it when coding in JavaScript.

Overview

If you're not interested in the gory details, you can jump to the summary.

So what is this?

ECMA-262 says it depends

Here is the official description of the this keyword from the ECMA-262 Edition 3 specification:

There is a this value associated with every active execution context. The this value depends on the caller and the type of code being executed and is determined when control enters the execution context. The this value associated with an execution context is immutable.

Helpful, I know. Also perfectly true.

Execution context

In JavaScript, functions are associated with execution contexts. There is also a shared global context for the code inside the <script> tags.

this is assigned when a context is activated.

When a script is parsed and executed, first the global execution context is activated, then the global code evaluated. As functions are called, their contexts are activated for the duration of their execution.

There are a few important points here:

  1. At no point within a script is this undefined
  2. Every execution context gets its own this
  3. The this in a function body is not associated with a value until the function is executed

In browser-land, window—the global object—is assigned to this in the global execution context.

<script>
// this === global object (window)
this.name = "The window.name property";

function getName() {
    return this.name;  // 'this' is unassigned until...
}

// when executed, getName's 'this' is assigned a value.  In this case window.
getName();
</script>

For code not in a function body, this will always be window. That's the easy part. The remainder of this article will deal primarily with divining the value of this inside functions.

The four ways of affecting what's in this

When functions are executed, their context is activated and their this set in one of four ways, depending on how the function is called.

Per the nomenclature used in Douglas Crockford's JavaScript: The Good Parts, the four ways to execute a function in JavaScript are:

Method Invocation: Executing a function from an object

The typical way of establishing this is by calling a method from an object.

myObject.getName = function () {
    return this.name;
};

// this === myObject
var name = myObect.getName();

This is your standard OOP syntax. It works pretty much how you expect. The this inside getName will refer to myObject.

Functions as class constructors

In JavaScript, what is commonly thought of as a class is manifest as just another function. The difference between a class function, or better called a constructor function, is the assumption of the this object in that function being a reference to a new instance of the class. Typically also the function's prototype object has a number of methods added to it to describe the new class's API. This usually looks something like this:

function MyClass() { // Upper case first letter by convention
    this.name = "foo"; // assume 'this' is a new instance of MyClass
}
MyClass.prototype.getName = function () {
    return this.name;
};

// instantiate the class with new
var instance = new MyClass();
var instance3 = new MyClass (); // also works
var instance2 = new MyClass; // also works

The new operator causes an instance of the class to be created and provided to the body of the constructor function as the this object. This is called Constructor invocation, and is another OOP no-brainer; this is the new instance.

new resolves whatever is to its right before an opening paren or semicolon. This can lead to code that looks like a mix of Method invocation and Constructor invocation. Constructor wins.

var instance = new myObject.Delegate(arg1,arg2);

// is equivalent to
var DelegateConstructor = myObject.Delegate;
var instance = new DelegateConstructor(arg1, arg2);

// NOT equivalent to
var DelegateConstructor = myObject.Delegate(arg1,arg2);
var instance = new DelegateConstructor;

Default context == window

When there's nothing to the left of a function name at the moment of execution—that is, no myObject.getName() or new MyClass(args)—the global object (window) is used as the value of this (with one exception).

<script>
function getName() {
    alert(this.name);
}

getName(); // this === window
</script>

This is called Function invocation. The root of many bugs is when a developer expects a function to be called via Method or Constructor invocation, but is in fact called via Function invocation. Examples of this include forgetting the new operator before a constructor function call or executing a sequestered instance method.

function MyClass(name) {
    this.name = name; // if this is window, this.name is a global assignment
}
MyClass.prototype.getName = function () {
    return this.name;
};

var oops = MyClass('oops!'); // Forgot new, this is window and that's bad
oops.getName(); // BOOM.  MyClass treated as a function returns undefined

var instance = new MyClass('valid');

var getInstanceName = instance.getName; // pass the function reference
getInstanceName(); // returns window.name

In these cases, this is believed to reference an object instance, but actually references window, and either a runtime error will result or worse yet, the global environment is modified from that point, and errors don't manifest until later.

The with exception

The with statement can have the effect of making what appears to be a Function invocation actually be a Method invocation. Names inside a with block are first resolved against the object in the parenthese, and if that object has a property or method with such a name, it is used. But most importantly for the topic at hand, methods are executed as if called from that object.

myObject.getName = function () {
    return this.name;
};

with (myObject) {
    // this === myObject, even though it looks like Function invocation
    var name = getName();
}

But I must emphasize that the use of with is considered bad practice in JavaScript. Don't use it.

Establishing this - the not so basics

Function.prototype.call and apply

To further confuse empower its developers, JavaScript provides a fourth way of establishing the value of this in functions: Apply invocation. Apply invocation is accomplished using two Function.prototype methods, call and apply. They look like this:

var myObject = { amount : 100 };

function myFunc(x,y,z) {
    return Math.round((this.amount - x + y) / z);
}

var total = myFunc.call(myObject, 20, 4, 2); // this === myObject. result: 42
// OR
var total = myFunc.apply(myObject, [ 20, 4, 2 ]); // same

The two methods call and apply differ only in signature. They both take the desired value for this as the first parameter, but after that, call takes individual parameters, where apply takes a single array of parameters.

Native JavaScript functions as well as any functions you create can be executed in this manner, passing almost any value as this. That goes for instance methods as well.

myObject.getName.call( myOtherObject ); // this === myOtherObject

It should be noted that all bets are off for DOM object methods (e.g. element.appendChild(..)) and other methods implemented by the browser environment that aren't described in the ECMAScript specification (such as alert(...) or setTimeout(...)).

A function's this is not portable

As illustrated with getInstanceName above, functions are first class objects and can be passed around like any other object. But functions do not carry with them any reference to the object they were grabbed from. This causes a lot of confusion when attempting to pass around instance methods.

function MyClass(name,data) {
    this.name = name;
    this.data = data;
    this.someFunction = function () { return this.data[0] * 100; };
}
var instance = new MyClass('foo', [ 1, 2, 3 ]});

var myString = instance.name; // pass string copy
var myArray = instance.data; // pass array reference

var myFunc = instance.someFunction; // pass function reference. Does not execute

var myVal1 = instance.someFunction(); // Executed. instance is this.  myVal1 == 100

var myVal2 = myFunc(); // ???

A common misconception is that since someFunction was defined as a method of the MyClass instance, that executing myFunc() is equivalent to calling instance.someFunction().

It is not.

As stated above, when a function is executed, what's to the left of the function name becomes this.

// Nothing to the left, so default to window
var myVal2 = myFunc(); // BOOM.  this === window, NOT instance

The someFunction function may have been initially assigned as a method of our MyClass class, but it's just a dumb function. It has no allegiance to any object. this is meaningless in the function body until it is executed.

If one were to create another class and steal that function for its prototype, like so...

function MyOtherClass(name) {
    this.name = name;
    this.data = [ 2, 4, 6 ];
}
MyOtherClass.prototype.getName = function () {
    return this.age;
};
MyOtherClass.prototype.someFunction = instance.someFunction;

var instance2 = new MyOtherClass("bar");
alert(instance2.someFunction()); // 200

...calling the stolen someFunction from the instance of the new class via Method invocation will pass instance2 as the this object for this. And what do you know, instance2 has a data property as well, so the function works like a champ!

Functions are not intrinsically bound to any object, so references to this in the function body are not guaranteed to be an instance of your class.

That said, this is rarely a problem if you just define classes and their functions, create instances of those classes and call the methods from the instances.

Where this often causes trouble for the uninitiated is when attempting to subscribe to DOM events with instance methods.

function MyClass(val) {
    this.property = val;
}
MyClass.prototype.getValue = function () {
    return this.property;
}

var instance = new MyClass('foo');

var button = document.getElementById('the_button');
button.onclick = instance.getValue; // <-- BAD

What happens in the onclick assignment is that the right hand side of the operation is evaluated, and the resulting value is assigned to the variable named in the left hand side. So instance.getValue is resolved to a function object (leaving instance behind), and that standalone function is assigned to the onclick property.

When the button is clicked, the function getValue will be executed, but its relation to instance is forgotten. As described below, inside the function body, this will refer to the button element.

DOM event handlers

There are three ways to attach DOM event handlers to elements:

  1. HTML attribute - <input type="button" onclick="doSomething()" value="go">
  2. Element property - button.onclick = doSomething;
  3. DOM Event model API - button.addEventListener("click",doSomething,false);

Most of them set this to the element whose event you subscribed to.

<!-- 1. set via HTML attribute -->
<input type="button" id="foo" name="foo" value="FOO" onclick="doSomething(this.value)">

<input type="button" id="bar" name="bar" value="BAR">
<input type="button" id="baz" name="baz" value="BAZ">
<script>
var bar = document.getElementById('bar'),
    baz = document.getElementById('baz');

// 2. Set via Element property
bar.onclick = clickHandler;

// 3. Set via DOM Event model API
if (baz.attachEvent) {
    baz.attachEvent("onclick", eventListener); // Only works in IE
} else if (baz.addEventListener) {
    baz.addEventListener("click", eventListener, false); // will not work in IE
}

function doSomething(val) {
    alert(val); // default context. this === window
}

function clickHandler() {
    alert(this.value); // this === bar
}

function eventListener(e) {
    alert(this.value); // BOOM.  this === window in IE.  this === baz in all others
}
</script>

In option #1, the browser wraps the attribute string in a function which will be executed with the element assigned to this. So this.value will refer to the input's attribute. The function doSomething will be executed in the global context.

In option #2, the clickHandler function reference (note no perens) is assigned to the event handler attribute. The handler will be executed with its this assigned to the element.

In option #3, IE's attachEvent implementation throws a curveball into the equation. Rather than set this to the element, the attached handler is executed in the global context. this is window. In all other browsers, the addEventListener API is provided and the attached handler is executed with the element assigned to this.

Most JavaScript libraries provide event subscription APIs that handle IE's odd behavior by leveraging closures to ensure the value in this.

Protecting this using closures

There are two common closure patterns for protecting this, both of which are used most often with instance methods:

  1. From inside an instance method storing this in a variable for access in inner functions
  2. From outside an instance method, binding a method to an instance
Storing this for use in nested functions

this should not be mistaken for a variable. Variables are declared by the code author, but this is assigned automatically, and can't be reassigned in the function body. Variables can be used in closures, but a new this is assigned to every function, including nested functions.

function XHR(domain) {
    this.uriBase = 'http://'+domain+'/';
    this.lastResponse = null;
}
XHR.prototype.createXHR = function (uri) {...};
XHR.prototype.sendRequest = function (resource,callback) {
    var xhr = this.createXHR(this.uriBase + resource);

    // nested function gets its own this
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            // this here does not point to the XHR instance
            this.lastResponse = xhr.responseText; // OOPS!
            callback();
        }
    }
    xhr.send(null);
}

To reference the outer function's this, simply assign it to a variable in the outer function's scope. Inner functions have access to the variables declared in the outer function.

XHR.prototype.sendRequest = function (resource,callback) {
    var xhr = this.createXHR(this.uriBase + resource),
        that = this; // store this for closure

    // nested function gets its own this
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            that.lastResponse = xhr.responseText; // that is sendRequest's this
            callback();
        }
    }
    xhr.send(null);
}

By convention, variables used to store this for reference in inner functions are called that, self, or me.

Binding methods to an object

To bind an instance method to a specific instance, create a new function to wrap the execution of the method from that instance, then pass around the wrapping function.

function MyClass(amount) {
    this.amount = amount;
}
MyClass.prototype.getAmount = function () {
    return this.amount;
};

var instance = new MyClass(100);

// Method invocation
var boundGetAmount = function (arg1,arg2,...) {
    // notice no reference to this
    return instance.getAmount(arg1,arg2,...);
};
// OR Apply invocation
var boundGetAmount = function () {
    return MyClass.prototype.getAmount.apply(instance,arguments);
};

// Executes instance.getAmount();
boundGetAmount(); // 100

var instance2 = new MyObject(3);

// boundGetAmount doesn't refer to this, so Apply invocation has no effect
boundGetAmount.call(instance2); // Still 100 

Most JavaScript frameworks have some sort of bind function allowing you to lock your functions to a specified this. Here is an example implementation:

var arraySlice = Array.prototype.slice;
function bind(fn,ctx) {
    var args = arraySlice.call(arguments,2);
    return function () {
        fn.apply(ctx,args.concat(arraySlice.call(arguments)));
    }
}

var button = document.getElementById('the_button');
button.onclick = bind(instance.method, instance, button);
// when the_button is clicked, this will point to instance rather than button

Weird values of this

Because of the flexibility afforded by Apply invocation and JavaScript's treatment of functions as first class objects, it is possible to set up some unique object/code structures where this is definitely not your typical OOP class instance.

CAVEAT: This section is informational only. The code patterns illustrated below are not recommended.

Executable this

Since Functions are Objects, they can have properties or even functions added to them. Executing a child function via Method invocation will cause this to be the parent function. The same effect can be created by passing a function reference as the first parameter to aFunc.call or .apply (Apply invocation).

function add(x,y) {
    return x + y;
}
add.to5 = function (x) {
    return this(x,5);
};

add(5,6); // 11
add.to5(6); // 11 -- Method invocation sets this to the add function

add.to5.call(function (x,y) { return x * y; }, 6); // 30

Along similar lines, you can use Method or Apply invocation with instances of other native objects such as RegExp.

var myRegex = /\bb\w+\b/gi;
myRegex.capitalize = function (str) {
    return str.replace(this,function (m) { return m.toUpperCase(); });
};

myRegex.capitalize("foo bar foo baz"); // "foo BAR foo BAZ"

myRegex.capitalize.call(/\b\w+/,"foo bar baz"); // foo BAR baz
this is always an Object

JavaScript ensures this is an instance of Object by using the global object in place of null or undefined, and wrapping primitive types in their native Object representation.

function whatIsThis() {
    var t = typeof this;
    if (t === 'object') {
        return Object.prototype.toString.call(this);
    } else {
        return t;
    }
}

whatIsThis.call();         // '[object Window]'* (undefined,null become window)
whatIsThis.apply(null);    // '[object Window]'* (undefined,null become window)
whatIsThis.call(false);    // '[object Boolean]' (Boolean, not boolean)
whatIsThis.apply('');      // '[object String]'
whatIsThis.call(0);        // '[object Number]'
whatIsThis.apply([1,2,3]); // '[object Array]'
whatIsThis.call({foo:'bar'}); // '[object Object]'
whatIsThis.call(whatIsThis);  // 'function' (functions are also acceptable)

* IE reports DOM objects and even their functions as [object Object]. So for example, window, a <div> element, and even document.getElementById will all report as typeof 'object' and toString as "[object Object]".

Overloading global object this

As with the direct contents of <script> tags, functions executed via Function invocation or sometimes Apply invocation will contain window in this. That means these snippets are equivalent:

function getA(id) {
    // document is not declared lexically, so it is found on the global object
    return document.getElementById(id);
}
function getB(id) {
    // window is not declared lexically, so it is found on the global object.
    // The window object contains a property 'window' that points to itself
    return window.document.getElementById(id);
}
function getC(id) {
    // this returns window when executed via Function invocation or Apply
    // invocation, passing window, null, or undefined as the first param
    return this.document.getElementById(id);
}

getA('foo'); // or getA.call(null,'foo');
getB('foo'); // or getB.call(null,'foo');
getC('foo'); // or getC.call(null,'foo');

Access to the DOM is acheived via the document property of window. Using a combination of with and Apply invocation, it is possible to reference a different global object (in all cases but undeclared variable assignment) making, for example, document refer to a different window's DOM.

<div id="target">OUTER</div>
<iframe id="inner" src="/local/uri" ...></iframe>
<script>
function doSomething() {
    alert("I'm the outer window");
}

// Create an anonymous function, and execute using Apply invocation, passing in
// the window object of the iframe as this
(function () {
    // Use with to add the iframe's window to the scope chain
    with (this) {
        // looks in the iframe's document
        var el = document.getElementById('target'); // likely null

        // window refers to the iframe's window.window
        el = window.document.getElementById('target'); // likely null

        // this refers of course to the iframe's window
        el = this.document.getElementById('target'); // likely null

        // Function invocation will first look at global functions in the iframe
        // window, then in the outer window.
        doSomething(); // ???
    }
}).call(document.getElementById('inner').contentWindow);
</script>

Recommendations

JavaScript makes this a very flexible reference, but if you follow some basic guidelines when authoring your code, you can decrease the likelihood of this-related bugs.

  1. Avoid referencing this in functions that are not constructors or instance methods.
  2. Uppercase the first character in class constructor functions.
  3. For constructors that modify this in potentially harmful ways, use the Factory/Constructor pattern, or extract the dangerous code into an initializer method.
  4. When sequestering methods from an instance or assigning them to an event handler, first bind them using a closure.
  5. For object methods that create function callbacks, store this in a local variable and use that instead.
  6. Avoid creative uses of this.
  7. use JSLint, build out test coverage, and test test test!

Stick to OOP when using this

// BAD
var MySingleton = {
    do_A : function (x) {
        x = this.do_B(x);
        return x - 8;
    },
    do_B : function (x) {
        return x + 10;
    }
};

MySingleton.do_A(40); // 42

var do_A = MySingleton.do_A;
do_A(40); // BOOM


// GOOD
var MySingleton = {
    do_A : function (x) {
        x = MySingleton.do_B(x);
        return x - 8;
    },
    do_B : function (x) {
        return x + 10;
    }
};

MySingleton.do_A(40); // 42

var do_A = MySingleton.do_A;
do_A(40); // 42

Class names should have an uppercase first letter

// BAD
function foo(val) {
    this.val = val;
}

var f1 = new foo(23);


// GOOD
function Foo(val) {
    this.val = val;
}

var f1 = new Foo(23);

The Factory/Constructor pattern

// BAD
function Student(name, focus) {
    this.name = name;
    this.focus = focus;
}

var instance = new Student('John','Math'); // OK
var oops = Student('Jane','Physics'); // silent BOOM! window.name and focus method reassigned


// GOOD
function Student(name, focus) {
    // if this is anything but a Student instance, we correct to use new
    if (!(this instanceof Student)) {
        return new Student(name,focus);
    }
    this.name = name;
    this.focus = focus;
}

var instance = new Student('Phyllis','Finance'); // OK
var oops = Student('Rod','Geometry'); // Still OK

The value of initializer methods

Initializers make for easier class extension, in-production maintenance, or run time class behavior modification since you can't change constructor code without creating an entirely new class constructor function.

// BAD
function Student(name, focus) {
    this.name = name;
    this.focus = focus;
}

var instance = new Student('John','Math'); // OK
var oops = Student('Jane','Physics'); // silent BOOM! window.name and focus method reassigned


// GOOD
// Fail-fast so long as there is no global function named construct(..)
function Student(name, focus) {
    this.construct(name,focus);
}
Student.prototype.construct = function (name,focus) {
    this.name = name;
    this.focus = focus;
};

var instance = new Student('Henry','Economics'); // OK
var oops = Student('Harry','Magic'); // Runtime error, but window not modified

Packaging instance methods for portability

// BAD
var button = document.getElementById('the_button');
button.onclick = instance.method;


// GOOD
var button = document.getElementById('the_button');
button.onclick = function (e) { instance.method(e); };

// OR use/create a generic bind function
var arraySlice = Array.prototype.slice;
function bind(fn,ctx) {
    var args = arraySlice.call(arguments,2);
    return function () {
        fn.apply(ctx,args.concat(arraySlice.call(arguments)));
    }
}

button.onclick = bind(instance.method, instance, button);

Store this in a local variable for callbacks

// BAD
function MyClass(val) {
    this.value = val;
}
MyClass.prototype.schedule = function (x, wait) {
    setTimeout(function () {
        this.value = x;
    }, wait);
};


// GOOD
function MyClass(val) {
    this.value = val;
}
MyClass.prototype.schedule = function (x, wait) {
    var that = this;
    setTimeout(function () {
        that.value = x;
    }, wait);
};

Weird is bad

// BAD
function add(x,y) {
    return x + y;
}
add.to5 = function (x) {
    return this(x,5);
};


// GOOD
function add(x,y) {
    return x + y;
}
add.to5 = function (x) {
    return add(x,5);
};

Use code checkers and test extensively

You should always delint your code using JSLint, and build up a test suite using one of the many JavaScript test frameworks freely available on the web.

// BAD
// likely typo. Assignment in if conditional
if (myVar = someValue) {
    // returns undefined because syntax states return value must start inline
    return
        myVar > someMin ?
            myVar :
            someMin;
}

JSLint will catch such errors, and save you a lot of headaches. It may also hurt your feelings, but at least your code will benefit.

Summary

Programmers of classical languages are used to seeing this in object methods as a reference to the current class instance. JavaScript uses this more broadly, so that assumption can get you into trouble. In fact, in JavaScript there is always an available this, and four ways to affect the value in it. Here is a quick run down of things to keep in mind with regards to this:

  1. this inside <script> tags (not inside a function) is window
  2. Every function gets its own this
  3. this is assigned when a function is executed
  4. Functions are executed via Method invocation, Constructor invocation, Function invocation, or Apply invocation
  5. Functions can be passed around like other objects
  6. this in instance methods probably won't point to the instance if the method is not executed via Method invocation
  7. All but IE's attachEvent set this to the element for DOM event handlers
  8. Closures are your friend
  9. Delint and use JavaScript test frameworks to validate your code
<script>
// global object this is window
var domElem = this.document.getElementById('the_button');

// Constructor invocation.
var myObject = new MyClass(arg), // common
    obj2     = new MyNamespace.MyOtherClass(arg), // function resolved first
    obj3     = new MyClass; // parens optional when no params needed

// Method invocation.  this === myObject
var value = myObject.someFunc();

// Passing a function reference.  No parens, not executed.
var fnRef = myObject.someFunc;

// Function invocation.  this === window
fnRef();

// Apply invocation.  this === myObject.  Equiv to myObject.someFunc(arg1, arg2...)
fnRef.call(myObject, arg1, arg2,...);

// Same.  Note different signature.
fnRef.apply(myObject, [arg1, arg2,...]);

// DOM0 event handler.  Note no parens.  this === domElem
domElem.onclick = myObject.someFunc;

// Non-IE DOM Event API subscription.   No parens.  this === domElem
domElem.addEventListener('click', fnRef, false);

// IE DOM Event API subscription. No parens. this === window (stupidly)
domElem.attachEvent('onclick', fnRef);

// Use closures to reference instance this inside nested functions/callbacks
MyClass.prototype.schedule = function (newVal,wait) {
    var that = this;
    setTimeout(function () {
        that.value = newVal; // this !== that
    },wait);
};

// Use function wrappers to bind a method to an instance before passing around
domElem.onclick = function (e) { myObject.someFunc(e); };
</script>