I have a constructor function which registers an event handler:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', function () {
        alert(this.data);
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);

However, I'm not able to access the data property of the created object inside the callback. It looks like this does not refer to the object that was created but to an other one.

I also tried to use an object method instead of an anonymous function:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

but it exhibits the same problems.

How can I access the correct object?

30 upvote
  flag
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome! – Felix Kling
upvote
  flag
upvote
  flag
upvote
  flag
Useful TypeScript page about this, mostly applicable to JS too. – Ondra Žižka

5 Answers 11

up vote 885 down vote accepted

What you should know about this

this (aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scope, like other variables. Here are some examples:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

To learn more about this, have a look at the MDN documentation.


How to refer to the correct this

Don't use this

You actually don't want to access this in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self and that.

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

Since self is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this value of the callback itself.

Explicitly set this of the callback - part 1

It might look like you have no control over the value of this, because its value is set automatically, but that is actually not the case.

Every function has the method .bind [docs], which returns a new function with this bound to a value. The function has exactly the same behavior as the one you called .bind on, only that this was set by you. No matter how or when that function is called, this will always refer to the passed value.

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

In this case, we are binding the callback's this to the value of MyConstructor's this.

Note: When binding context for jQuery, use jQuery.proxy [docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.

ECMAScript 6: Use arrow functions

ECMASCript 6 introduces arrow functions, which can be thought of as lambda functions. They don't have their own this binding. Instead, this is looked up in scope just like a normal variable. That means you don't have to call .bind. That's not the only special behavior they have, please refer to the MDN documentation for more information.

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

Set this of the callback - part 2

Some functions/methods which accept callbacks also accept a value to which the callback's this should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map [docs] is such a method. Its signature is:

array.map(callback[, thisArg])

The first argument is the callback and the second argument is the value this should refer to. Here is a contrived example:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

Note: Whether or not you can pass a value for this is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax method [docs] describes an option called context:

This object will be made the context of all Ajax-related callbacks.


Common problem: Using object methods as callbacks / event handlers

Another common manifestation of this problem is when an object method is used as callback / event handler. Functions are first class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.

Consider the following example:

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

The function this.method is assigned as click event handler, but if the body is clicked, the value logged will be undefined, because inside the event handler, this refers to the body, not the instance of Foo.
As already mentioned at the beginning, what this refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

The solution is the same as mentioned above: If available, use .bind to explicitly bind this to a specific value

document.body.onclick = this.method.bind(this);

or explicitly call the function as a "method" of the object, by using an anonymous function has callback / event handler and assign the object (this) to another variable:

var self = this;
document.body.onclick = function() {
    self.method();
};

or use an arrow function:

document.body.onclick = () => this.method();
14 upvote
  flag
Felix, I've read to this answer before but never replied. I grow concerned that people use self and that to refer to this. I feel this way because this is an overloaded variable used in different contexts; whereas self usually corresponds to the local instance and that usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use _this, but am not sure how others feel, except for the non-uniform practice that has resulted. – vol7ron
upvote
  flag
@FelixKling, it allows you to be super lazy with code like $(...).on('click', $.proxy(obj, 'function')) and $(...).off('click', obj.function). – zzzzBov
upvote
  flag
Hey, any chance you'd add a section on the ES7 :: bind syntax proposal, or would you prefer to wait until it's more finalized than not? – ndugger
upvote
  flag
@Nick: No, I'm OK with adding it.... although, I just saw that it's still stage 0. I think waiting for stage 1 would make sense. – Felix Kling
1 upvote
  flag
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that? – andig
2 upvote
  flag
@FelixKling It can be useful at times to rely on Function.prototype.call () and Function.prototype.apply (). Particularly with apply () I've gotten a lot of mileage. I am less inclined to use bind () perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options. – Nolo
upvote
  flag
If you're using Typescript, fix this using arrow functions. (This can be deduced from Felix Kling's answer, but it's somewhat long-winded, giving lots of (neat) options. The linked answer is much more direct for Typescript.) – rinogo
upvote
  flag
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all. – Aluan Haddad
upvote
  flag
Would it be worth exampling the use of EventListener interface in the cases of DOM events and other objects that might implement EventTarget? Or would that be straying off as it would only work for those cases. – Patrick Evans

It's all in the "magic" syntax of calling a method:

object.property();

When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:

var f = object.property;
f();

When you get the reference of a method, it's no longer attached to the object, it's just a reference to a plain function. The same happens when you get the reference to use as a callback:

this.saveNextLevelData(this.setAll);

That's where you would bind the context to the function:

this.saveNextLevelData(this.setAll.bind(this));

If you are using jQuery you should use the $.proxy method instead, as bind is not supported in all browsers:

this.saveNextLevelData($.proxy(this.setAll, this));

The trouble with "context"

The term "context" is sometimes used to refer to the object referenced by this. It's use is inappropriate because it doesn't fit either semantically or technically with ECMAScript's this.

"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope and this within the scope of some executing code.

This is shown in ECMA-262 section 10.4.2:

Set the ThisBinding to the same value as the ThisBinding of the calling execution context

which clearly indicates that this is part of an execution context.

An execution context provides the surrounding information that adds meaning to code that is being executed. It includes much more information that just the thisBinding.

So the value of this isn't "context", it's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.

Here are several ways to access parent context inside child context -

  1. You can use bind() function - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
  2. Store reference to context/this inside another variable
  3. Use ES6 Arrow functions - https://derickbailey.com/2015/09/28/do-es6-arrow-functions-really-solve-this-in-javascript/
  4. Alter code/function architecture - for this you should have commands on design patterns in javascript - https://addyosmani.com/resources/essentialjsdesignpatterns/book/

1. Use bind() function

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', ( function () {
        alert(this.data);
    }).bind(this) );
}
// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};
// called as
var obj = new MyConstructor('foo', transport);

If you are using underscore.js - http://underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));

2 Store reference to context/this inside another variable

function MyConstructor(data, transport) {
  var self = this;
  this.data = data;
  transport.on('data', function() {
    alert(self.data);
  });
}

3 Arrow function

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

First you need to have a clear understanding of "scope" and behavior of "this" keyword in the context of "scope".

"this" & "scope" :


there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope

in short , global scope refers to the window object.Variables declared in global context is accessible from anywhere.On the other hand function scope resides inside of a function.variable declared inside a function can not be accessed from outside world normally."this" keyword in global scope refers to window object."this" inside function also refers to window object.So "this" will always refers to window until we find a way to manipulate "this" to indicate a context of our own choosing.

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to window object also                   -
-                                                                              -
-         }                                                                    -
-                                                                              -
-         outer_function(callback_function)                                    -
-         // invoke with callback                                              -
--------------------------------------------------------------------------------

Different ways to manipulate THIS in callback with example :

Here i have a constructor function called Person. It has a property called "name" and four method called "sayNameVersion1","sayNameVersion2","sayNameVersion3","sayNameVersion4". All four of them has one specific task.Accept a callback and invoke it.The callback has a specific task which is to log the name property of instance of Person constructor function.

function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // function to be used as callback

    var parentObject = this

    console.log(parentObject)

}

Now lets create an instance from person constructor and invoke different versions of "sayNameVersionX" method with "niceCallback" to see how many ways we can manipulate the "this" inside callback to refer to the person instance.

var p1 = new Person('zami') // create an instance of Person constructor

bind :

What bind do is to create a new function with the "this" keyword set to the provided value.

sayNameVersion1 and sayNameVersion2 use bind to manipulate "this" of the callback function.

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

first one bind "this" with callback inside the method itself.And for the second one callback is passed with the object bound to it.

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

call :

First argument of the "call" method is used as this inside the function that is invoked with "call" attached to it.

sayNameVersion3 uses call to manipulate the "this" to refer to the person object that we created instead of the window object.

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

and it is called like the following :

p1.sayNameVersion3(niceCallback)

apply :

Similar to "call" , first argument of apply refers to the object that will be indicated by "this" keyword.

sayNameVersion4 uses apply to manipulate "this" to refer to person object

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

and it is called like the following .Simply the callback is passed ,

p1.sayNameVersion4(niceCallback)
upvote
  flag
any constructive criticism regarding the answer will be appreciated ! – AL-zami

Not the answer you're looking for? Browse other questions tagged or ask your own question.