Ключевое слово this
Специальное слово в языке JavaScript, которое позволяет методам объектов и функциям получить доступ к информации внутри объекта.
Что же значит this? В коде это слово заменяет имя объекта, информацию из которого мы пытаемся получить. В зависимости от того, какой объект вызывает метод, будет меняться и значение this.
Давайте рассмотрим пример. Создадим объект user с данными пользователя:
let user = {
name: "John",
age: 30,
}
Теперь добавим нашему объекту метод sayHi, который будет выводить имя пользователя. Для этого методу потребуется доступ к информации, содержащейся в объекте, и вот тут нам и пригодится слово this.
let user = {
name: "John",
age: 30,
sayHi() {
}
};
Впишите внутри фигурных скобок метода sayHi следующее:
alert(this.name);
Посмотрите, что вернет код:
sayHi {
}
Итак, вот что у нас получилось:
let user = {
name: "John",
age: 30,
sayHi() {
alert(this.name);
}
};
А теперь вызовите метод sayHi из объекта user. Для этого допишите последнюю строчку кода — user.sayHi(); — и посмотрите на результат.
Метод sayHi вызывается объектом user, поэтому в данном примере значением this является user.
Конечно, мы можем получить имя пользователя и без помощи this — просто обратившись к объекту через внешнюю переменную, в которой хранится ссылка на этот объект. Между фигурными скобками метода sayHi впишите alert(user.name);, т.е. замените в коде this на user. Что вернёт код?
let user = {
name: "John",
age: 30,
sayHi() {
// "user" вместо "this"
}
};
Метод sayHi в данном случае тоже вернет John. Зачем же тогда писать лишние строчки кода и использовать this?
Дело в том, что обращаясь к данным объекта напрямую через переменную, мы ставим работу нашего кода в зависимость от этой переменной. Если мы сохраним ссылку на объект в другую переменную, например, admin = user, и перезапишем саму переменную user, код будет работать неправильно. Метод sayHi выдаст ошибку при работе с объектом admin.
let user = {
name: "John",
age: 30,
sayHi() {
alert( user.name ); // приведёт к ошибке
}
};
let admin = user;
user = null; // перезапишем переменную для наглядности, теперь она не хранит ссылку на объект.
admin.sayHi(); // TypeError: Cannot read property 'name' of null
Чтобы методы всегда работали с данным объектом, тем самым, который их вызывает, мы и используем ключевое слово this.
this не является фиксированным
В JavaScript ключевое слово this ведёт себя иначе, чем в большинстве других языков программирования. Его можно использовать в любой функции, даже если это не метод объекта.
В следующем примере нет синтаксической ошибки:
function sayHi() {
alert( this.name );
}
Значение this вычисляется во время выполнения кода, в зависимости от контекста.
Например, здесь одна и та же функция назначена двум разным объектам и имеет различное значение this в вызовах:
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert( this.name );
}
// используем одну и ту же функцию в двух объектах
user.f = sayHi;
admin.f = sayHi;
// эти вызовы имеют разное значение this
// "this" внутри функции - это объект "перед точкой"
user.f(); // John (this == user)
admin.f(); // Admin (this == admin)
admin['f'](); // Admin (нет разницы между использованием точки или квадратных скобок для доступа к объекту)
Правило простое: если вызывается obj.f(), то во время вызова f, this – это obj. Так что, в приведённом выше примере это либо user, либо admin.
У стрелочных функций нет this
Стрелочные функции особенные: у них нет своего «собственного» this. Если мы ссылаемся на this внутри такой функции, то оно берётся из внешней «нормальной» функции.
Например, здесь arrow() использует значение this из внешнего метода user.sayHi():
let user = {
firstName: "Ilya",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
user.sayHi(); // Ilya
Это особенность стрелочных функций. Она полезна, когда мы на самом деле не хотим иметь отдельное this, а скорее хотим взять его из внешнего контекста.
Подведем итог
- Методы могут ссылаться на объект через
this. - Значение
thisопределяется во время исполнения кода. - При объявлении любой функции в ней можно использовать
this, но этотthisне имеет значения до тех пор, пока функция не будет вызвана. - Функция может быть скопирована между объектами (из одного объекта в другой).
- Когда функция вызывается синтаксисом «метода» –
object.method(), значениемthisво время вызова являетсяobject. - Cтрелочные функции являются особенными — у них нет
this. Когда внутри стрелочной функции обращаются кthis, то его значение берется извне.