Привет, ребята, в этом случае я хочу погрузиться в ключевое слово это в Javascript: что это такое и откуда оно взялось, не потому, что нет сотен статей, которые уже рассмотрели его, а потому, что я лично думаю, что это часто
слишком много объяснений и, следовательно, должно создать много путаницы.
Во-первых, когда мы говорим об этом загадочном ключевом слове, мы говорим о контексте выполнения, то есть , функции. По умолчанию всякий раз, когда функция выполняется, Javascript создает этот объект и передает его в качестве другого аргумента, поэтому мы можем использовать указанный объект как любую обычную переменную. И я говорю по умолчанию, потому что от этого поведения можно отказаться, используя строгий режим, но я расскажу об этом позже.

Таким образом, «это» может быть связано с функциями. Хорошо. Но о чем мы говорим, когда я говорю «функции»? Ну… буквально любой блок кода, который можно вызвать. Но вот когда это может запутать, существует более одного элемента, который соответствует указанным критериям: функции (обычные функции) и методы. Чтобы не погружаться слишком глубоко, предположим, что между ними есть одно основное различие: методы вызываются, синтаксически связывая их с объектом, поэтому obj.method() (в отличие отпросто функции ()). И JS отслеживает это и присваивает значение this в зависимости от того, какое из двух используется.

Таким образом, в случае «обычных» функций JS (опять же, по умолчанию) присваивает им глобальный объект (что зависит от среды).

В случае методов он присваивает ему объект-владелец.

И это оченьстрого. Рассмотрим следующий пример:

const myObj = { myMethod() { console.log(this) } }
myObj.myMethod()
const myFunction = myObj.myMethod
myFunction()

В первом вызове мы очевидно вызываем метод, потому что перед ним очень милая точка, а перед точкой находится объект-владелец.

Теперь во втором вызове представьте, что на первых трех строках кода есть большое черное пятно, поэтому мы не можем видеть, что под ним. Мы никак не можем знать, что говорим о методе. И это именно то, что происходит: нас нет. Мы говорим о нормальной функции. Поэтому второй пример, как было сказано ранее, напечатает глобальный объект, а первый? Будет печатать myObj. И это все, что нужно сделать. Это было не так уж и важно, не так ли?

Если вы разработчик React, у вас могут быть привязанные методы к экземпляру вашего компонента. Почему это? Ну… это из-за такого же поведения. Когда вы делаете что-то вроде:

<button onClick={this.focusTextInput}>Focus the text input</button>

Значение onClick теперь указывает непосредственно на метод, как и в предыдущем примере. Поскольку мы сначала назначаем его onClick , а затем вызываем его оттуда, связь между указанным методом и его объектом-владельцем прерывается и теперь действует как обычная функция. Но почему «это» становится неопределенным вместо globalThis? Потому что мы находимся под завесой «строгого режима». Цитирую Мозилла:

Значение, переданное как this функции в строгом режиме, не принудительно становится объектом (также известным как «упакованный»).

… Таким образом, для функции строгого режима указанный this не помещается в объект, и если он не указан, this будет undefined.

Javascript всегда применяет строгий режим для классов, я скоро до них доберусь.

Теперь есть несколько исключений, о которых важно поговорить.

Стрелочные функции

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

const myObj = { myMethod: () => console.log(this) }
myObj.myMethod()
const myFunction = myObj.myMethod
myFunction()

Если вы запустите этот пример, вы увидите, что в обоих случаях консоль будет регистрировать глобальный объект. Так что это не значит, что «это» ни к чему не привязано, оно просто связано внешней областью видимости, которая передает значение. Короче говоря, стрелочные функции получают значение this из внешней области видимости.

Здесь очень важно отметить, что не все фигурные скобки составляют допустимую область видимости, и это случай фигурных скобок объекта. Итак, в предыдущем случае внешняя область видимости является основной функцией.

Разберем более сложный пример:

const myObj = {
  prop1: () => {
    function f1() { console.log(this); }
    f1();
  },
  prop2() {
    const f2 = () => (() => console.log(this))();
    f2();
  },
  prop3() {
    function f3() {
      const f4 = () => console.log(this);
       f4();
    }
    f3();
  },
};
myObj.prop1();
myObj.prop2();
myObj.prop3();

Как вы думаете, что консоль будет регистрировать в каждом случае? Подумайте на минуту…

prop1 → глобальный объект

prop2 → мой объект

prop3 → глобальный объект

Итак, теперь, когда это не так, давайте объясним еще несколько случаев: знаменитые .bind(), .call() и .apply().

.bind(), .call() и .apply()

Что делает .bind(), так это заставляет функцию всегда иметь свой объект this равным любому значению -object-, которое вы передали в качестве аргумента (поэтому он используется в React с классами). .call() и .apply() делают почти то же самое, они вызывают указанную функцию с ее значением this, привязанным к объекту, переданному в качестве аргумента, только один раз. Рассмотрим следующее:

const map = {one: true, two: true, hasOwnProperty: () => false};
console.log(map.hasOwnProperty("one")); // false

Откуда мы знаем наверняка, что объект владеет свойством, называемым «один»?

console.log(Object.hasOwnProperty.call(map, 'one'));

Наконец, некоторые примеры классов были бы интересны, чтобы закрыть это.

Классы

class MyClass {
  func = (function () {
    console.log(this, 1);
  })();
  arrowFunc = (() => {
    console.log(this, 2);
  })();
  constructor() {
    (() => console.log(this, 3))();
    (function () {
      console.log(this, 4)
    })();
  }
}
new MyClass()

Попробуйте угадать выходы, они могут быть хитрыми.

журнал 1 → не определено. Из-за строгого режима обычные функции «отвязывают» «это».

журнал 2 → Объект { функция: не определено }. Поскольку стрелочная функция не завершилась во время регистрации, arrowFunc еще не объявлен.

log 3 → Object { func: undefined, arrowFunc: undefined }. Конструктор привязан к экземпляру.

журнал 4 → не определено. То же, что 1.

Вот и все! Надеюсь, мне удалось развеять некоторые сомнения. Хорошего дня!