W3docs

How to Access the Correct “this” Inside a Callback

In the following tutorial, you can find the answer to one of the most common issues in JavaScript: how to access the correct “this” inside a callback.

From time to time, the keyword this may become a source of pain for developers.

In this short tutorial, we will give the answers to one of the most common issues in JavaScript: how to access the correct “this” inside a callback.

<kbd class="highlighted">this</kbd> is a special keyword inside any function, and its value depends on how the function was called but not how, where or when it was defined. It is not affected by lexical scopes, just like other variables.

Let’s take a look at the following cases:

Javascript this

javascript— editable

Note: In strict mode, a plain function call assigns undefined to this instead of window.

If you need to access the object that <kbd class="highlighted">this</kbd> refers to, you can store it in a new variable. Common naming conventions are <kbd class="highlighted">that</kbd> and <kbd class="highlighted">self</kbd>. This is demonstrated in the example below:

Javascript this

function ConstructorFunc(data, transport) {
  this.data = data;
  let self = this;
  transport.on('data', function () {
    console.log(self.data);
  });
}

Setting this inside the callback

You may not have control over the value of <kbd class="highlighted">this</kbd> because it is determined automatically. However, you can control it explicitly.

Each function has a .bind() method that returns a new function with <kbd class="highlighted">this</kbd> bound to a specific value. The returned function behaves like the original, but <kbd class="highlighted">this</kbd> is explicitly set by you. Regardless of where and when the function is called, <kbd class="highlighted">this</kbd> will refer to the bound value, as follows:

javascript this inside callback

function ConstructorFunc(data, transport) {
  this.data = data;
  let boundFunc = (function () { // parentheses aren’t necessary but might improve readability
      console.log(this.data);
    }
  ).bind(this); //  here we are calling `.bind()`
  transport.on('data', boundFunc);
}

In such a case, you are binding the callback <kbd class="highlighted">this</kbd> to the value of the Constructor’s <kbd class="highlighted">this</kbd>.

ECMAScript 6 introduced arrow functions, which behave like lambda functions. Arrow functions do not have their own <kbd class="highlighted">this</kbd> binding. Instead, <kbd class="highlighted">this</kbd> is looked up in the enclosing scope as a regular variable. This means you are not required to call <kbd class="highlighted">.bind</kbd>. However, arrow functions have other unique behaviors.

Now, let’s check out the following example:

Javascript this inside callback

function ConstructorFunc(data, transport) {
  this.data = data;
  transport.on('data', () => console.log(this.data));
}

Some functions and methods that accept callbacks also accept a second argument specifying what <kbd class="highlighted">this</kbd> should refer to inside the callback. This achieves the same result as manual binding, but the method handles it for you:

javascript this inside callback

arr.map(callback[, thisArg])

The first argument is the callback, and the second argument is the value <kbd class="highlighted">this</kbd> should refer to.

For instance:

Javascript this inside callback

javascript— editable

Another common scenario occurs when an object method is used as a callback handler. In JavaScript, functions are first-class citizens, and the term “method” simply refers to a function that is a property of an object. When detached, the function loses its link to the containing object:

Let’s consider this example:

Javascript this inside callback

function Func() {
  this.data = 20,
  document.body.onclick = this.method;
}
Func.prototype.method = function () {
  console.log(this.data);
};

In the example above, <kbd class="highlighted">this.method</kbd> is assigned as a click event handler. If you click <kbd class="highlighted">document.body</kbd>, the logged value will be <kbd class="highlighted">undefined</kbd>. This happens because inside the event handler, <kbd class="highlighted">this</kbd> refers to <kbd class="highlighted">document.body</kbd>, not the <kbd class="highlighted">Func</kbd> instance.

As we have already noted, <kbd class="highlighted">this</kbd> always depends on how the function is called, and not on how it is defined.

In the example below, you can notice that the function doesn’t obtain an inherent reference to an object:

Javascript this inside callback

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

function Func() {
  this.data = 20,
 document.body.onclick = this.method;
}
Func.prototype.method = method;

So, the solution will be as follows:

javascript this inside callback

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

Alternatively, you can call the function as a method of the object, like this:

javascript this inside callback

let val = this;
document.body.onclick = function () {
  val.method();
};

Another option is using an arrow function:

javascript this inside callback

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

The Description of Object methods, “this”

In JavaScript, objects are generated to represent real-world entities, such as users, orders, and so on.

Functions stored as properties can represent actions in JavaScript. A function that is a property of an object is called a method. Additionally, a pre-declared function can be applied as a method.

this is a special keyword inside any function, and its value depends on how the function was called but not how, where, or when it was defined.

Unlike many other programming languages, in JavaScript, <kbd class="highlighted">this</kbd> can be used in any function.