Ключове слово this — це просто

Ключове слово this — це просто

  • 12 липня, 2023
  • читати 7 хв
Олександра Донцова
Олександра Донцова Front-end Developer у Sigma Software, Викладач Комп'ютерної школи Hillel.

JavaScript є однією з найпопулярніших мов програмування у світі, вона широко використовується для розробки веб-додатків.

Однією з найважливіших концепцій у JavaScript є ключове слово «this». Воно використовується для посилання на поточний об'єкт у контексті виконання коду. Хоча на початку може здатися, що «this» — це складна тема, насправді вивчити її не так важко.

І я вас запевняю, що після прочитання цієї статті у вас не залишиться питань щодо «цього»! :-)

Тож поїхали:

THIS в методі обʼєкту

«This» часто використовують в об'єктних літералах.

Об'єктні літерали — це швидкий спосіб створення об'єктів у JavaScript. У цьому контексті «this» вказує на об'єкт, в якому він знаходиться.

Розглянемо приклад:

const person = {
    name: "John",
    age: 25,
    sayHello: function () {
        console.log(`Привіт, я ${this.name}`);
    },
};


person.sayHello(); // Виведе "Привіт, я John"

В цьому прикладі ми створюємо об'єкт person з властивостями name і age, а також методом sayHello. У методі sayHello ми використовуємо «this» для посилання на об'єкт person і виведення значення властивості name.

THIS в класах

Іншим частим використанням «this» є контекст функцій-конструкторів.

Функції-конструктори використовуються для створення нових об'єктів на основі певного шаблону. У такому контексті «this» вказує на об'єкт, який створюється.

Розглянемо наступний приклад:

function Person(name, age) {
    this.name = name;
    this.age = age;
}


const john = new Person("John", 25);
console.log(john.name); // Виведе "John"
console.log(john.age); // Виведе 25

У цьому прикладі функція-конструктор Person має два параметри — name і age. Коли ми створюємо новий об'єкт за допомогою оператора new, «this» вказує на цей об'єкт. Тому властивості name і age присвоюються саме цьому об'єкту.

THIS в функціях

Використання «this» може бути не таким очевидним, коли його використовують в звичайних функціях або зв'язаних методах. У звичайних функціях «this» зазвичай вказує на глобальний об'єкт window (у браузері) або глобальний об'єкт global (у середовищі Node.js).

Наприклад:

function greet() {
    console.log(`Привіт, я ${this}`);
}


greet(); // Виведе "Привіт, я [object Window]" (у браузері)

У цьому прикладі «this» вказує на глобальний об'єкт window, оскільки функцію greet викликають у глобальному контексті.

Щоб зрозуміти значення «this» в зв'язаних методах, потрібно звернути увагу на контекст виклику. Контекст виклику — це об'єкт, на якому викликається метод. Для правильного використання «this» у зв'язаних методах можна використовувати методи bind, call або apply.

Наприклад:

const person = {
    name: "John",
    age: 25,
};


function sayHello () {
    console.log(`Привіт, я ${this.name}`);
}


sayHello.call(person);  // Виведе "Привіт, я John"

У цьому прикладі ми використовуємо метод call для прив'язки до контексту функції sayHello об'єкта person. Це дозволяє зберегти правильний контекст «this» незалежно від того, яким чином викликається метод.

THIS в стрілковій функції

У стрілкових функціях в JavaScript «this» має особливу поведінку. Вони не мають власного значення «this» і беруть його з контексту, у якому вони були створені. Це означає, що «this» в стрілковій функції буде мати таке саме значення, як і «this» в зовнішній області видимості, де вона була оголошена.

Ось приклад, щоб продемонструвати це:

// Зовнішня функція, яка містить стрілкову функцію
function outerFunction() {
    // Властивість "name" належить об'єкту, у якому викликається зовнішня функція
    this.name = "John";


    // Стрілкова функція внутрішня до зовнішньої функції
    const innerArrowFunction = () => {
        // Виведе "John", беручи значення "this" з контексту зовнішньої функції
        console.log(this.name);
    };


    innerArrowFunction(); // Виклик стрілкової функції
}


outerFunction(); // Виклик зовнішньої функції

У цьому прикладі стрілкова функція innerArrowFunction бере значення «this» з контексту зовнішньої функції outerFunction, оскільки вона була оголошена всередині неї. Тому, коли ми викликаємо innerArrowFunction, вона виведе «John», оскільки this.name посилається на name у зовнішній функції.

Важливо зазначити, що стрілкові функції не можуть бути використані як функції-конструктори і не мають власного значення «this». Тому вони не підходять для використання в ситуаціях, коли потрібно мати контроль над значенням «this» або використовувати ключові слова, такі як super або arguments.

THIS в анонімній функції

У анонімних функціях JavaScript поведінка «this» залежить від контексту, в якому вони були викликані. Вони не мають власного значення «this» і отримують його з батьківського контексту.

Ось приклад, щоб продемонструвати це:

// Об'єкт, який містить метод і анонімну функцію
const obj = {
    name: "John",
    sayHello: function () {
        console.log(`Hello, ${this.name}`);
        // Виводить "Hello, John" - this посилається на об'єкт obj


        (function () {
            console.log(`Inside anonymous function: ${this.name}`);
            // Виводить "Inside anonymous function: undefined" - this не має власного значення
        })();
    }
};


obj.sayHello(); // Виклик методу sayHello

У цьому прикладі метод sayHello має доступ до this.name, оскільки він був викликаний на об'єкті obj. Однак анонімна функція всередині методу sayHello не має власного значення «this». Тому, коли ми спробуємо вивести this.name всередині анонімної функції, вона виведе undefined, оскільки «this» відсутнє у контексті цієї функції.

Для отримання доступу до батьківського контексту, де this відповідає очікуваному об'єкту, можна зберегти посилання на «this» у змінній, яку потім можна використовувати всередині анонімної функції.

Наприклад:

const obj = {
    name: "John",
    sayHello: function () {
        const self = this; // Зберегти посилання на this у змінній self
        (function () {
            console.log(`Inside anonymous function: ${self.name}`); // Виведе "Inside anonymous function: John"
        })();
    }
};


obj.sayHello(); // Виклик методу sayHello

Використання змінної self дозволяє отримати доступ до очікуваного значення «this» всередині анонімної функції.

А в чому ж різниця між THIS в стрілковій та анонімних функціях?

Головна різниця між «this» в стрілковій функції та анонімній функції в JavaScript полягає в їхньому поведінці стосовно прив'язки «this».

У стрілкових функціях:

  1. Вони не мають власного значення «this». Вони беруть значення «this» з контексту, в якому вони були створені. Це означає, що «this» в стрілковій функції буде мати таке саме значення, як «this» у зовнішньому обсязі видимості, де вона була оголошена.

  2. Вони не можуть бути використані як функції-конструктори. Тому не можна створити екземпляр об'єкта за допомогою стрілкової функції.

  3. Вони не мають доступу до ключових слів super та arguments.

  4. Вони зручні для використання в контекстах, де потрібно мати доступ до значень «this» з зовнішнього контексту.

З іншого боку, у анонімних функціях:

  1. Вони можуть мати власне значення «this», яке визначається контекстом виклику. Значення «this» в анонімній функції залежить від того, як саме вона була викликана.

  2. Вони можуть бути використані як функції-конструктори для створення нових об'єктів.

  3. Вони мають доступ до ключових слів super та arguments, які дозволяють отримувати доступ до батьківських об'єктів та аргументів функції відповідно.

  4. Вони зручні для використання в контекстах, де потрібно динамічно прив'язати значення «this» до об'єкту, який викликав функцію.

Як визначати «this» в JavaScript?

Отже, для визначення «this» JavaScript можна виділити таку схему:

  • Викликається глобальна функція?

Так: «this» посилається на глобальний об'єкт (наприклад, window у браузері або global в Node.js).

  • Викликається функція-метод об'єкта?

Так: «this» посилається на об'єкт, на якому була викликана функція.

  • Викликається функція-конструктор за допомогою new?

Так: «this» посилається на новостворений функцією-конструктором об'єкт.

  • Використовується метод call, apply або bind?

Так: «this» встановлюється явно через перший аргумент методу call, apply або bind.

  • Використовується стрілкова функція?

Так: «this» береться з батьківського контексту, де вона була створена, і не може бути змінене.

  • Використовується анонімна функція?

Залежить від контексту, в якому анонімна функція була викликана. Це може бути глобальний об'єкт, об'єкт, на якому була викликана функція, або може бути власне значення «this», встановлене явно.

Це і є загальна схема для визначення «this» в JavaScript. При розгляді конкретних випадків важливо враховувати контекст виклику та особливості використання методів та функцій в коді.

Сподіваюсь після цих розʼяснень ви більше ніколи не згубете своє «це».

Дякую за увагу! :-)

Рекомендуємо курс по темі