JS Tower
JavaScript & TypeScriptМодуль 6: ООП и паттерны

Контекст this

Как определяется this в JavaScript

Цель урока

В этом уроке ты научишься:

  • Понимать, что такое this
  • Определять значение this в разных ситуациях
  • Управлять контекстом с помощью bind, call, apply

Что такое this

this — ссылка на объект, в контексте которого выполняется функция.

let user = {
  name: "Иван",
  greet() {
    console.log("Привет, " + this.name);
  }
};

user.greet(); // "Привет, Иван"

Правила определения this

1. Метод объекта

let user = {
  name: "Иван",
  greet() {
    console.log(this.name);
  }
};

user.greet(); // this = user

2. Обычная функция

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

showThis(); // window (браузер) или undefined (strict mode)

3. Конструктор (new)

function User(name) {
  this.name = name;
}

let user = new User("Иван");
console.log(user.name); // "Иван"
// this = новый объект

4. Стрелочная функция

let user = {
  name: "Иван",
  greet: () => {
    console.log(this.name); // undefined!
  }
};

// Стрелочные функции не имеют своего this
// Они берут this из внешнего окружения

Потеря контекста

let user = {
  name: "Иван",
  greet() {
    console.log("Привет, " + this.name);
  }
};

let greet = user.greet;
greet(); // "Привет, undefined" — потеря контекста!

// Решение 1: привязка
let boundGreet = user.greet.bind(user);
boundGreet(); // "Привет, Иван"

// Решение 2: стрелочная функция
setTimeout(() => user.greet(), 1000);

bind, call, apply

bind — создаёт новую функцию с привязанным this

let user = { name: "Иван" };

function greet(greeting) {
  console.log(greeting + ", " + this.name);
}

let boundGreet = greet.bind(user);
boundGreet("Привет"); // "Привет, Иван"

// С частичным применением
let sayHello = greet.bind(user, "Привет");
sayHello(); // "Привет, Иван"

call — вызывает функцию с указанным this

let user = { name: "Иван" };

function greet(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

greet.call(user, "Привет", "!"); // "Привет, Иван!"

apply — как call, но аргументы массивом

let user = { name: "Иван" };

function greet(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

greet.apply(user, ["Привет", "!"]); // "Привет, Иван!"

Стрелочные функции и this

let user = {
  name: "Иван",
  friends: ["Мария", "Пётр"],
  
  showFriends() {
    // Стрелочная функция берёт this из showFriends
    this.friends.forEach(friend => {
      console.log(this.name + " дружит с " + friend);
    });
  }
};

user.showFriends();
// "Иван дружит с Мария"
// "Иван дружит с Пётр"

Практика

Задание 1: Определи this

Задача: Что выведет код?

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Объект

Задание 2: bind

Задача: Привяжи контекст к функции.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
5

Задание 3: Стрелочная функция

Задача: Исправь потерю контекста.

Loading...
Ваш вывод:

Проверь себя

  1. Что такое this?
  2. Чем bind отличается от call?
  3. Почему стрелочные функции не имеют своего this?