JavaScript execution context management

JavaScript execution context management

Hello, Habre! Today we will talk about thisbecause without a clear understanding of how it works thisyour code can become a source of confusion and errors.

this JS is a keyword that refers to the current execution context. Its value depends on where and how the function was called, not where it was defined.

In this article, we’ll break down all the ways to work with execution context so you can use it with confidence this in any scenario.

Different contexts

Global context: The behavior of this outside of functions

When you are at the top level of code without functions and objects this refers to a world object. In browsers it is windowand in Node.js – global.

console.log(this); // В браузере выведет объект window

Here this refers to a world object. If you use this outside of any context, you will always get a global object.

But how will this affect the function? Consider the following example:

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

showContext(); // Вызовет функцию, выведет window (или global в Node.js)

Agree, this behavior can surprise, especially if you expected that this will refer to something else. If you want to this pointed to a specific object in the global context, you need to wrap it in another object:

const myObject = {
    name: 'My Object',
    showContext: showContext,
};

myObject.showContext(); // выведет myObject

Object Context: How it refers to the current object in methods

When a function is called as a method of an object, this indicates the object to which the method belongs. This is perhaps one of the most convenient features this.

const user = {
    name: 'Polina',
    greet() {
        console.log(`Hello, my name is ${this.name}`);
    },
};

user.greet(); // Hello, my name is Polina

In this example, when greet() is called this refers to an object userand we access its properties. But what happens if we pass the method to another function?

const greetFunc = user.greet;
greetFunc(); // Hello, my name is undefined

Here this no longer points to userbecause the method was called outside the context of the object.

Functional Context: Differences between calling functions as methods and regular functions

When a function is called simply as a function (not as a method of an object), this again points to a global object (in strict mode it will undefined).

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

showThis(); // window (или undefined в strict mode)

But if you call the function as a method of the object, this will refer to the object:

const obj = {
    value: 42,
    showValue() {
        console.log(this.value);
    },
};

obj.showValue(); // 42

Arrow functions: An explanation of why this does not change in arrow functions

Arrow functions save this from the surrounding context. That is, this in the arrow function will be the same as and this in the parent function where it was declared:

const person = {
    name: 'Ivan',
    greet: function () {
        const arrowFunc = () => {
            console.log(`Hi, I'm ${this.name}`);
        };
        arrowFunc();
    },
};

person.greet(); // Hi, I'm Ivan

Here is an arrow function arrowFunc preserves the context thiswhich points to an object person.

However, be careful: if you try to use the arrow function in object methods, it will cause this will not refer to the object:

const obj = {
    name: 'Artem',
    show: () => {
        console.log(this.name);
    },
};

obj.show(); // undefined

Here this refers to a global object (or undefined in strict mode), and you will not get the expected result.

Changing the execution context

Now let’s see how to manage the execution context using methods call, apply and bind. These tools allow you to customize what is referenced thisdepending on your desire.

The call, apply, and bind methods: how and when to use them to control the context

Method call allows calling a function with the specified value this and arguments passed separately.

func.call(thisArg, arg1, arg2, ...);
const person = {
    name: 'Artem',
};

function greet(greeting) {
    console.log(`${greeting}, my name is ${this.name}`);
}

greet.call(person, 'Hello'); // Hello, my name is Artem

We use callto indicate that this in the function greet refers to an object person. We also pass the argument 'Hello'that the function uses.

Method apply works similarly callbut accepts array arguments.

func.apply(thisArg, [argsArray]);
const person = {
    name: 'Nikita',
};

function greet(greeting, punctuation) {
    console.log(`${greeting}, my name is ${this.name}${punctuation}`);
}

greet.apply(person, ['Hi', '!']); // Hi, my name is Nikita!

Method bind creates a new function that will have the specified value when called thisand can even accept predefined arguments. Unlike call and apply, bind does not call the function immediately, but returns a new function.

const boundFunction = func.bind(thisArg, arg1, arg2, ...);
const person = {
    name: 'Charlie',
};

function greet(greeting) {
    console.log(`${greeting}, my name is ${this.name}`);
}

const greetCharlie = greet.bind(person);
greetCharlie('Hey'); // Hey, my name is Charlie

Here we create a new function greetCharliewhich will always refer to the object person.

Classes and context: how to work with this in classes

When we work with JavaScript classes, it’s important to remember that this in class methods indicates an instance of the class. However, if you pass a class method as a callback, this can get lost

Example:

const person = {
    name: 'Dave',
};

function introduce(greeting, age) {
    console.log(`${greeting}, I am ${this.name} and I am ${age} years old.`);
}

introduce.call(person, 'Hello', 30); // Hello, I am Dave and I am 30 years old.
introduce.apply(person, ['Hi', 25]); // Hi, I am Dave and I am 25 years old.

Here we use bind in the constructor to make sure that this always refers to an instance Personeven if the method is called outside the context of the class. If we didn’t use bindwe would get undefined in this.name during the call greet through setTimeout.

Other features

Strict Mode: Prevent unexpected values ​​from this

Strict mode is a way to set rules that help avoid errors, simplify diagnostics, and improve code security. In strict mode, if the function is called without a context (like a normal function), this will be undefinedrather than referencing a global object.

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

showThis(); // В браузере выведет window

An example with strict mode:

'use strict';

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

showThis(); // undefined

Object methods and that

When you define methods on objects, it is important to remember that this inside the method, the object itself will always be referenced, even if the method is passed to another function or context. However, if you do not use bindYou may encounter unexpected results.

Example:

const obj = {
    name: 'Eva',
    showName() {
        console.log(this.name);
    },
};

const show = obj.showName;
show(); // undefined (в строгом режиме) или 'Eva' (в обычном)

Here, when we call show, this does not indicate objwhich leads to unexpected results.

this in event handlers

When you add an event handler, this it usually refers to the element that the event is set to.

Example:



However, if you use an arrow function as a handler, this will point to the parent context, not the element.

Example with an arrow function:



Implicit and explicit this

JavaScript distinguishes between implicit and explicit this. Implicit this is when this is determined automatically depending on how the function was called. Apparent this is when you use methods call, apply or bindto clearly indicate what is being referred to this.

Implicit this:

const car = {
    brand: 'Ford',
    showBrand() {
        console.log(this.brand);
    },
};

car.showBrand(); // Ford

Apparent this:

function showBrand() {
    console.log(this.brand);
}

const myCar = { brand: 'Toyota' };

showBrand.call(myCar); // Toyota

Keep your code clear, a this under control Remember that this — the thing is capricious, but, like any good instrument, in skillful hands it works wonders.


OTUS experts tell more about programming languages ​​in practical online courses. The full catalog of courses can be found at the link.

Related posts