
Простая визуальная диаграмма, которая поможет вам понять «это» в Javascript
10 февраля 2023 г.Этот пост поможет вам понять, как легко узнать значение «this
» в JavaScript. Если вы спешите, в конце есть шпаргалка по этому ключевому слову JavaScript.
Ключевое слово «this
» в JavaScript сбило с толку многих разработчиков, но с помощью всего 4 простых правил вы больше никогда не запутаетесь.
Во-первых, вам нужно знать одну важную вещь при работе с ключевым словом «this
»
это
привязка не во время автора, а привязка во время выполнения, поэтому речь идет не о том, где объявляется функция, а о том, как она вызывается
Когда я говорю об «этих привязках», я просто имею в виду, как ключевому слову «это» присваивается значение. В JavaScript существует 4 разных типа привязок «this», и у них есть собственный порядок старшинства. Итак, вот 4 разных привязки «этого» в порядке возрастания приоритета. Как ключевое слово this работает в JavaScript — привязка по умолчанию.
Как ключевое слово this работает в JavaScript — привязка по умолчанию
Большинство вызовов функций в вашем коде будут иметь привязку по умолчанию. Значение this привязано к глобальному объекту (объект окна при работе с JavaScript в браузере). Это происходит, когда вы вызываете функцию, указав только имя функции и ее аргументы в квадратных скобках.
<цитата>Примечание. Если функция находится в строгом режиме, то по умолчанию «это» относится к неопределенному. При работе в модуле JavaScript строгий режим включается автоматически.
function foo() {
this.a = 4;
/**
* creates a global variable a
* this is the same as doing these things
* var a = 4;
* or window.a = 4;
**/
}
foo();
console.log(a); // 4
function bar() {
"use strict";
/**
* since this is undefined in strict mode
* the a variable cannot be set and it
* results in an error
*/
this.a = 6;
console.log(a);
}
bar(); // TypeError: Cannot set property 'a' of undefined
Что такое ключевое слово this в классе JavaScript — привязка класса
Этот тип привязки происходит, когда вы вызываете функцию как метод объекта. Значением this является сам объект.
obj = {
a: 4,
foo: function() {
console.log(this.a);
}
};
obj.foo(); // 4
Неважно, где вы объявляете функцию, если вы вызываете ее как метод объекта.
function foo() {
console.log(this.a);
}
obj = {
a: 7,
foo: foo
};
obj.foo(); // 7
Имеет значение только верхний/последний уровень цепочки ссылок свойств объекта.
function foo() {
console.log(this.a);
}
const obj1 = {
a: 4,
foo: foo
};
const obj2 = {
a: 7,
obj1: obj1
};
obj2.obj1.foo(); // 4
/*
Here, obj2 is accessing it's obj1 property
and then since, the obj1 property is an object itself,
it calls it's own foo method,
which accesses the a variable set in the obj1 object so it logs the value 4.
*/
Самое важное, что нужно помнить, это то, что речь идет не о самой функции. Дело в том, как это называется. Например, здесь мы вызываем функцию foo, но поскольку она вызывается не как метод объекта, мы возвращаемся к привязке по умолчанию «this».
function foo() {
console.log(this.a);
}
const obj = {
a: 7,
foo: foo
};
/**
* only a reference to the actual function is assigned
* it does not care about the implicit binding
*/
const bar = obj.foo;
var a = 11;
/**
* here this refers to the window object because of
* default binding
**/
bar(); // 11
Как связать это в JavaScript — явное связывание с вызовом и применением
Большинство встроенных функций и все пользовательские функции имеют два специальных служебных метода; подать заявку и позвонить. Вы можете использовать эти методы для явной привязки значения this. Значение «this» легко вычислить, потому что оно явно передается в качестве первого аргумента методам вызова или применения.
function foo() {
console.log(this.a);
}
const obj = {
a: 4
};
/**
* calls the foo function
* where this is bound to the obj object
*/
foo.call(obj); // 4
Примечание: оба метода apply и call работают одинаково для явной привязки this к заданному значению, но способ передачи в других аргументах немного отличается. Возможно, вы также использовали метод .bind() es6 до этого, который использует явную привязку под капотом, вы можете прочитать больше об этом здесь.
Как это работает в JavaScript с новым ключевым словом — новая привязка
Чтобы понять этот тип привязки, необходимо понять, как работают конструкторы в JavaScript. В JavaScript конструкторы — это просто функции, которые вызываются с оператором «new» перед ними. Они не привязаны к классам и не создают экземпляр класса. Это обычные функции, захваченные с помощью ключевого слова «новое».
Любая определяемая пользователем или встроенная функция может быть вызвана с «новым» перед ней, и это делает ее вызовом построения. Нет такой вещи, как функции-конструкторы, а есть вызовы функций.
Вот что происходит, когда вы звоните на стройку:
- Создается совершенно новый объект.
- Новый объект связан с прототипом.
- Объект устанавливается как привязка this для вызова функции
- Если функция не вернет собственный альтернативный объект, вызов новой вызванной функции вернет вновь созданный объект.
function foo() {
this.a = 4;
}
const bar = new foo(); // bar is set to the newly created object;
console.log(bar.a); // 4
Как это работает в стрелочной функции — привязка стрелочной функции
Я знаю, что обещал, что будет только 4 разных типа привязки this, и в прошлом это было правдой, пока в es6 не появились стрелочные функции.
/**
* arrow functions use the fat arrow =>
* instead of the function keyword.
*/
a => {
console.log(a);
};
Стрелочные функции — это не только более быстрый способ написания функций, но и немного отличающаяся привязка «этого». Они используют лексический объем для «это». Чтобы узнать больше о лексической области видимости, ознакомьтесь с моим руководством по лексической области действия и замыканию.
Они наследуют значение «это» от своей внешней функции. Под «внешней функцией» я подразумеваю функцию, в которой вы объявляете стрелочную функцию, а не там, где вы их вызываете.
function foo() {
var = 3;
return () => {
/**
* here this actually refers to the
* this of the foo function
*/
console.log(this.a); // 3
};
}
Вот более сложный пример, в котором используются другие способы привязки this наряду с привязкой функции стрелки.
function foo() {
return () => {
/**
* here this actually refers to the
* this of the foo function
*/
console.log(this.a);
};
}
const obj1 = {
a: 4
};
const obj2 = {
a: 7
};
/**
* sets "this" binding to obj1 and
* gets the arrow function as the return value
* Now bar is a reference to the arrow function returned by the foo function
* */
const bar = foo.call(obj1);
/**
* tries to set the this binding
* of the arrow function to obj2 but
* the arrow function's this is set
* to the this of foo which was bound to obj1
**/
bar.call(obj2); // 4
Таким образом, привязка «этой» функции стрелки на самом деле выполняется во время разработки, а не во время выполнения, как и другие типы привязки «этой».
"this" в Резюме JavaScript и Шпаргалке
Вот что мы теперь знаем о том, как это работает в JavaScript:
* Ключевое слово this в JavaScript относится не к привязке времени автора, а к привязке времени выполнения, то есть речь идет не о том, где объявлена функция, а о том, как она вызывается. * В JavaScript существует 4 различных типа привязок this, каждый из которых имеет свой порядок приоритета: * Привязка по умолчанию: значение this привязано к глобальному объекту (объект окна при работе с JavaScript в браузере). Если функция находится в строгом режиме, то "this" относится к undefined. * Class Binding: значением this является сам объект при вызове функции как метода объекта. * Явное связывание с вызовом и применением: позволяет явно привязать значение this, передав желаемое значение в качестве первого аргумента в метод вызова или применения. * Неявное связывание: значением this является объект, свойством которого является функция. * Самое главное помнить, что дело не в самой функции, а в том, как она вызывается. * Стрелочные функции в JavaScript не имеют собственной привязки this, они наследуют значение this окружающей области видимости. Это означает, что значение this внутри стрелочной функции будет таким же, как значение this в коде, окружающем стрелочную функцию.
Вы можете использовать эту памятку, чтобы найти значение this в JavaScript. Итак, в следующий раз, когда будет сложно отладить значение «this», просто сохраняйте спокойствие и задавайте себе эти вопросы.
:::информация Также опубликовано здесь.
:::
Оригинал