В JavaScript ключевое слово «this» ведёт себя иначе, чем в большинстве других языков программирования. Оно может использоваться в любой функции.
В этом коде нет синтаксической ошибки:
function sayHi() {
alert( this.name );
}
Значение this
вычисляется во время выполнения кода и зависит от контекста.
Например, здесь одна и та же функция назначена двум разным объектам и имеет различное значение «this» при вызовах:
let user = { name: "Джон" };
let admin = { name: "Админ" };
function sayHi() {
alert( this.name );
}
// используем одну и ту же функцию в двух объектах
user.f = sayHi;
admin.f = sayHi;
// вызовы функции, приведённые ниже, имеют разное значение this
// "this" внутри функции является ссылкой на объект, который указан "перед точкой"
user.f(); // Джон (this == user)
admin.f(); // Админ (this == admin)
admin['f'](); // Админ (неважен способ доступа к методу - через точку или квадратные скобки)
Правило простое: при вызове obj.f()
значение this
внутри f
равно obj
. Так что, в приведённом примере это user
или admin
.
Вызов без объекта: this == undefined
Мы даже можем вызвать функцию вовсе без использования объекта:
function sayHi() {
alert(this);
}
sayHi(); // undefined
В строгом режиме ("use strict"
) в таком коде значением this
будет являться undefined
. Если мы попытаемся получить доступ к name
, используя this.name
– это вызовет ошибку.
В нестрогом режиме значением this
в таком случае будет глобальный объект (window
для браузера, смотри Глобальный объект). Это – исторически сложившееся поведение this
, которое исправляется использованием строгого режима ("use strict"
).
Обычно подобный вызов является ошибкой программирования. Если внутри функции используется this
, тогда ожидается, что она будет вызываться в контексте какого-либо объекта.
Последствия свободного this
Если вы до этого изучали другие языки программирования, тогда вы, скорее всего, привыкли к идее “фиксированного this
” – когда методы, определённые внутри объекта, всегда сохраняют в качестве значения this
ссылку на свой объект (в котором был определён метод).
В JavaScript this
является «свободным», его значение вычисляется в момент вызова метода и не зависит от того, где этот метод был объявлен, а зависит от того, какой объект вызывает метод (какой объект стоит «перед точкой»).
Эта идея вычисления this
в момент исполнения имеет как свои плюсы, так и минусы. С одной стороны, функция может быть повторно использована в качестве метода у различных объектов (что повышает гибкость). С другой стороны, большая гибкость увеличивает вероятность ошибок.
Здесь мы не будем судить о том, является ли это решение в языке хорошим или плохим. Мы должны понимать, как с этим работать, чтобы получать выгоды и избегать проблем.