managing execution context in JavaScript

In this article we will look at all the ways to work with execution context so that you can confidently use this in any scenario.

Different contexts this

Global context: this behavior outside functions

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

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

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

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

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

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

Agree, this behavior may surprise you, 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 this refers to the current object in methods

When a function is called as a method of an object, this points to 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() called, this refers to an object userand we get access to 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 indicates userbecause the method was called outside the object's context.

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 the global object (in strict mode this would be undefined).

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

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

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

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

obj.showValue(); // 42

Arrow Functions: Explaining Why This Doesn't Change in Arrow Functions

Arrow functions save this from the surrounding context. That is this in an arrow function will be the same as 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's an arrow function arrowFunc preserves context thiswhich points to an object person.

However, be careful: if you try to use an 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.

Call, apply and bind methods: how and when to use them to manage context

Method call allows you to call a function with a 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 function greet refers to an object person. We also pass the argument 'Hello'which the function uses.

Method apply works similarly callbut takes arguments as an array.

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, when called, will have the given value thisand can also take 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 classes in JavaScript, it is important to remember that this in class methods, points to an instance of the class. However, if you pass a class method as a callback, this may 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 class context. If we didn't use bindwe would get undefined V this.name when calling greet through setTimeout.

Other features

Strict mode: preventing unexpected this values

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

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

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

Example with strict mode:

'use strict';

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

showThis(); // undefined

Object methods and this

When you define methods on objects, it is important to remember that this inside a method will always refer to the object itself, even if the method is passed to another function or context. However, if you don't use bindyou may experience 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 on which the event is set.

Example:

<button id="myButton">Click me</button>

<script>
document.getElementById('myButton').addEventListener('click', function() {
    console.log(this); // будет ссылаться на <button>
});
</script>

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

Example with an arrow function:

<button id="myButton">Click me</button>

<script>
document.getElementById('myButton').addEventListener('click', () => {
    console.log(this); // будет ссылаться на родительский контекст, не на <button>
});
</script>

Implicit and explicit this

JavaScript distinguishes between implicit and explicit this. Implicit this – this is when this is determined automatically depending on how the function was called. Explicit this – this is when you use methods call, apply or bindto explicitly indicate what is being referenced this.

Implicit this:

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

car.showBrand(); // Ford

Explicit this:

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

const myCar = { brand: 'Toyota' };

showBrand.call(myCar); // Toyota

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


OTUS experts talk more about programming languages ​​in practical online courses. With a complete catalog of courses you can check out the link.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *