В JavaScript this
— это свойство контекста выполнения, в котором выполняется функция.
Объяснение того, как оценивается this
, очень сложное, и в этой статье MDN оно подробно рассматривается в каждом конкретном случае.
Значение this
функции определяется в основном тем, как функция вызывается в месте вызова, а не тем, как функция определена: например, включен ли строгий режим или нет, определена ли функция и вызывается автономно или нет, вызываем ли мы функцию как метод объекта или извлекаем ссылку на метод объекта и затем вызываем его в другом месте и т.д.
Контекст выполнения
Контекст выполнения функции — это среда, в которой функция выполняется во время исполнения. Он включает в себя область видимости переменных, аргументы функции и значение объекта this
.
this
Если нам нужна функция, которая действует на свойства объекта, который мы хотим использовать, то ее this
должен быть этим объектом. Другими словами, целевой объект нашей функции должен быть доступен контексту выполнения во время исполнения, чтобы мы могли обращаться к нему с помощью this
.
В обычном режиме this
— это всегда объект. Значения undefined
и null
автобоксируются в глобальный объект (объект window
в браузере). В строгом режиме, однако, это может быть undefined
или null
, поскольку в строгом режиме нет автобоксинга this
.
function testThis() {
return this;
};
console.log(testThis()); // [object Window]
function testThisInStrictMode() {
'use strict'
return this;
};
console.log(testThis()); // undefined
В объектах
Если у нас есть объект с методом, который использует this
, и мы вызываем метод на объекте, объект автоматически присваивается this
метода.
const person = {
name: 'Abd',
age: 42,
sayHi: function() {
return `Hi, this is ${this.name}`;
},
};
console.log(person.sayHi()); // "Hi, this is Abd"
То же самое относится к экземплярам пользовательских объектов, созданных с помощью функций конструктора, а также к классам.
// constructor function example
function Person() {
this.name = 'Abd';
this.age = 42;
this.sayHi = function() {
return `Hi, this is ${this.name}`;
};
};
const person = new Person();
console.log(person.sayHi()); // "Hi, this is Abd"
// class example
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
};
sayHi() {
return `Hi, this is ${this.name}`;
};
};
const person = new Person('Abd', 42);
console.log(person.sayHi()); // "Hi, this is Abd"
Ссылки на функции
Вероятно, самый яркий случай использования this
в JavaScript возникает, когда мы хотим извлечь ссылку на метод из объекта и затем вызвать его из другого места.
Например, если мы сохраним метод sayHi()
объекта person
(из любого примера выше) в переменной, а затем вызовем его позже, у нас не будет никакого объекта, заданного для действия метода. Мы фактически отделяем объект от функции, на которую ссылаемся, поэтому this
для этой функции во время выполнения будет либо глобальным объектом, либо undefined
в зависимости от того, в нормальном режиме или в строгом.
`use strict`
const sayHiAbd = person.sayHi; // Note that person.sayHi is NOT being invoked here
console.log(sayHiAbd()); // Error: Cannot read property 'name' of undefined
В этом сценарии sayHiAbd()
подобна отдельной функции, определенной следующим образом:
function sayHiAbd() {
return `Hi, this is ${this.name}`;
};
В таких случаях мы должны вызвать функцию с помощью .call()
или .apply()
, чтобы явно установить объект this
в месте вызова.
console.log(sayHiAbd.call({name: 'Abd', age: 42})); // "Hi, this is Abd"
Постоянное связывание
Если мы хотим навсегда привязать объект к функции, мы должны создать новую функцию с .bind()
, которая прикрепляет объект к новой функции.
const alwaysSayHiAbd = sayHiAbd.bind({name: 'Abd', age: 42});
console.log(alwaysSayHiAbd()); // "Hi, this is Abd"
Синтаксис стрелки
Синтаксис стрелок навсегда связывает окружающий лексический контекст определения функции с контекстом ее выполнения. Таким образом, контекст места вызова никогда не вмешивается в стрелочные функции.
В примере с объектным литералом person
выше, если мы модифицируем нашу функцию sayHi()
, чтобы вернуть стрелочную функцию, которая возвращает строку приветствия, то возвращаемая (стрелочная) функция this
привязывается к своему объемлющему лексическому контексту, которым является сам объект person
. Хранение ссылки на него и его вызов всегда указывают его this
на person
.
const person = {
name: 'Abd',
age: 42,
sayHi: function() {
return () => `Hi, this is ${this.name}`;
},
};
const sayHiAbd = person.sayHi();
console.log(sayHiAbd()); // "Hi, this is Abd"
Ссылки
- this
- Стандарт ECMAScript — ResolveThisBinding