Найти в Дзене

This в JavaScript, как он работает и почему все путаются

Народ, всем привет. this — одно из самых загадочных ключевых слов в JavaScript. Даже опытные разработчики периодически теряются, когда сталкиваются с его поведением. А причина проста, ведь значение this зависит не от места, где функция написана, а от того, как она вызвана. По факту, this — это ссылка на контекст выполнения функции. Проще говоря, он указывает на объект, из контекста которого вызвана функция. Пока сложно? Давайте на примерах: const user = { name: "Аня", sayHi() { console.log(this.name); } }; user.sayHi(); // "Аня" Здесь this внутри sayHi указывает на объект user, потому что метод был вызван через user.sayHi(). 1. В браузере, если вызвать функцию без объекта, this ссылается на глобальный объект window. function foo() { console.log(this); } foo(); // window (в браузере) Кстати, в строгом режиме ('use strict') значение будет undefined: 2. Если функция вызывается как метод объекта, this указывает на этот объект (то, о чем я написал выше). const cat = { name: "Мурка", meow()
Оглавление

Народ, всем привет. this — одно из самых загадочных ключевых слов в JavaScript. Даже опытные разработчики периодически теряются, когда сталкиваются с его поведением. А причина проста, ведь значение this зависит не от места, где функция написана, а от того, как она вызвана. По факту, this — это ссылка на контекст выполнения функции. Проще говоря, он указывает на объект, из контекста которого вызвана функция. Пока сложно? Давайте на примерах:

const user = {
name: "Аня",
sayHi() {
console.log(this.name);
}
};
user.sayHi(); // "Аня"

Здесь this внутри sayHi указывает на объект user, потому что метод был вызван через user.sayHi().

-2

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

1. В браузере, если вызвать функцию без объекта, this ссылается на глобальный объект window.

function foo() {
console.log(this);
}
foo(); // window (в браузере)

Кстати, в строгом режиме ('use strict') значение будет undefined:

2. Если функция вызывается как метод объекта, this указывает на этот объект (то, о чем я написал выше).

const cat = {
name: "Мурка",
meow() {
console.log(this.name + " мяукает");
}
};
cat.meow(); // "Мурка мяукает"
-3

3. А вот если метод вынести в переменную и вызвать отдельно, this "теряется":

const dog = {
name: "Шарик",
bark() {
console.log(this.name + " лает");
}
};
const barkFn = dog.bark;
barkFn(); // undefined (строгий режим) или window

Это одна из главных причин путаницы.

4. При вызове через new создаётся новый объект, и this ссылается уже на него:

function Person(name) {
this.name = name;
}
const p = new Person("Иван");
console.log(p.name); // "Иван"

В классах всё работает так же:

class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(this.name);
}
}
const u = new User("Оля");
u.sayHi(); // "Оля"
-4
Хотите знать больше? Читайте нас в нашем Telegram – там еще больше интересного: новинки гаджетов, технологии, AI, фишки программистов, примеры дизайна и маркетинга.

5. Особенность стрелочных функций в том, что у них нет собственного this. Они используют this из внешнего контекста:

const obj = {
name: "Лена",
arrow: () => {
console.log(this.name);
}
};
obj.arrow(); // undefined, потому что this взят из глобального контекста

Но это удобно в колбэках:

function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer(); // корректно считает секунды

Если бы мы использовали обычную функцию, this внутри setInterval потерялся бы.

-5

6. JavaScript позволяет вручную указывать контекст с помощью методов .call, .apply и .bind.

function greet() {
console.log(`Привет, ${this.name}`);
}
const user = { name: "Коля" };
greet.call(user); // "Привет, Коля"
greet.apply(user); // "Привет, Коля"
const boundGreet = greet.bind(user);
boundGreet(); // "Привет, Коля"

В чем разница?

  • call — вызывает функцию сразу, передавая аргументы через запятую;
  • apply — вызывает сразу, но аргументы принимает массивом;
  • bind — возвращает новую функцию с закреплённым контекстом.

Почему возникает путаница? Да потому что разные правила в разных ситуациях. В глобальном контексте, в методах, в стрелочных функциях this ведёт себя по-разному. И это легко забыть. Плюс автоматическая потеря контекста. Когда метод передаётся как колбэк, this часто становится undefined или window. Так еще и многие новички ожидают, что стрелка будет вести себя так же, как метод объекта, и удивляются результату.

-6

Как упростить жизнь с this?

Ну, например, использовать стрелочные функции там, где важно сохранить внешний контекст (setTimeout, setInterval, обработчики событий). А если нужно передавать метод как колбэк — привязывать контекст через .bind(). В классах можно использовать публичные поля со стрелочными функциями:

class Button {
text = "Кнопка";
click = () => {
console.log(this.text);
};
}
const b = new Button();
setTimeout(b.click, 1000); // "Кнопка"

Но главная причина путаницы именно то, что this не привязан к месту, где функция объявлена, и может "потеряться". Поэтому так важно помнить о правилах и использовать стрелочные функции или bind, когда нужен стабильный контекст.

-7

Если Вам нравятся наши статьи, и вы хотите отблагодарить автора (на развитие канала), нам будет очень приятно!