Explain Codes LogoExplain Codes Logo

How to access the correct this inside a callback

javascript
callback
this-binding
javascript-best-practices
Anton ShumikhinbyAnton Shumikhin·Sep 8, 2024
TLDR

To rectify this context speedily within a callback, pick arrow functions which lexically bind this, or switch to .bind() for your classic functions.

// Rocket speed - Arrow function setTimeout(() => console.log(this.value), 1000); // Classic - Bind method setTimeout(function() { console.log(this.value); }.bind(this), 1000);

With arrow functions, you enjoy brevity, while .bind(this) lets you display the this context on its forehead.

Keep this in a variable

In an environment devoid of arrow functions, worry not. The age-old hack is to assign this to another variable, mostly named self or that. Now this is accessible within the callbacks.

function MyFunction() { var self = this; // "self" here is the new cool kid in town this.value = 42; setTimeout(function() { console.log(self.value); // Showing off the value of cool kid }, 1000); }

This method is especially handy when attempting to bridge the gap between ES5 and ES6.

Carve this with .bind()

Take a stroll with .bind(). This method chisels this into a shape that you desire. It creates a new function that, when you call, adjusts its this keyword according to the value you provided.

function greeting() { console.log('Hello, ' + this.name); // Let's greet } var object = { name: 'Alice' }; var boundGreeting = greeting.bind(object); // Alice got tied up with greeting boundGreeting(); // Outputs: Hello, Alice

thisArg in Array methods: map, forEach, filter

Some Array methods like Array#map, Array#forEach, Array#filter get a kick out of playing with thisArg. This optional parameter strikes a pose, assigning a context to this, right inside the callback function.

const numbers = [1, 2, 3]; const multiplier = { value: 2, multiply() { return numbers.map(function(number) { return number * this.value; }, this); } }; console.log(multiplier.multiply()); // Outputs: [2, 4, 6]

Dealing with this in event handlers

In DOM event handlers, this usually signals to the element in receipt of the event. But hey, you can change reference of this just by using .bind().

document.querySelector('#myButton').addEventListener('click', function() { console.log(this); // Usually refers to #myButton }.bind(myObject)); // With .bind(), `this` gets a new face - myObject

Calling this in constructor functions

Introduce this to constructor functions in JavaScript, only to find them reciprocating by sharing secrets about this patterns within the constructor. When this isn't the expected instance, keeping this in line calls for arrow functions or .bind().

function Timer() { this.seconds = 0; setInterval(() => { this.seconds++; // `this` enjoys Timer's company }, 1000); // Ticks like a charm! }

jQuery's love for this

For jQuery users, call out to .proxy() function to manage this in your callbacks. In $.ajax(), the context option Readies.Set.Goes... your callbacks for the correct this value.

// With jQuery.proxy $('#myButton').on('click', $.proxy(function() { console.log(this); // `this` now takes the shape of myObject }, myObject)); // With `context` in $.ajax $.ajax({ url: 'my/api', context: myObject, success: function(response) { console.log(this); // `this` refers to myObject } });

Going back in time to legacy codebases, or specific frameworks? These solutions equip your callbacks for consistent functionality.

Strict 'mode' in ambiguous this

The 'use strict' mode has a thing for changing the behavior of this. In its world, this doesn't default to the global object, an essential nugget to remember.

function whatIsThis() { 'use strict'; console.log(this); } whatIsThis(); // undefined in strict mode

Advanced this patterns

As you progress, architectures such as modules or factories could lineup for this management.

Follow the script for this: ECMAScript standard

The ECMAScript standard maps the execution context and thisBinding. Grasp the script to uncover more about this.