JavaScript: что такое this?

От автора: определить значение this в JavaScript может быть непросто, однако… Тhis в JavaScript — предмет многих шуток, потому что, ну, это довольно сложно. Тем не менее, я видел, как разработчики делали гораздо более сложные и зависящие от предметной области вещи, чтобы избежать ключевого слова this. Если вы не уверены, надеюсь, это поможет. Это мое руководство по this.

Если функция определена как стрелочная функция:

В этом случае значение this является всегда тем же, что и this в родительской области:

Стрелочные функции хороши тем, что внутреннее значение this нельзя изменить, оно всегда такое же, как и внешнее this.

Другие примеры

При использовании стрелочных функций значение this нельзя изменить с помощью bind:

Для стрелочных функций значение this нельзя изменить с помощью call или apply:

В стрелочных функциях значение this нельзя изменить, вызвав функцию как член другого объекта:

В стрелочных функциях значение this нельзя изменить, вызвав функцию как конструктор:

‘Связанные’ методы экземпляра

С помощью методов экземпляра, если вы хотите, чтобы this всегда ссылались на экземпляр класса, лучший способ — использовать стрелочные функции и поля класса:

Этот шаблон действительно полезен при использовании методов экземпляра в качестве прослушивателей событий в компонентах (таких как компоненты React или веб-компоненты).

Вышеупомянутое может показаться нарушением правила «this будет таким же, как this в родительской области», но это имеет смысл, если вы думаете о полях класса как о синтаксическом сахаре для установки полей в конструкторе:

Альтернативные схемы включают привязку существующей функции в конструкторе или присвоение функции в конструкторе. Если по какой-то причине вы не можете использовать поля класса, разумной альтернативой является назначение функций в конструкторе:

В противном случае, если функция / класс вызывается с помощью new:

Вышеупомянутое вызовет Whatever (или его конструктор, если это класс) с установленным результатом this: Object.create(Whatever.prototype).

То же верно и для конструкторов такого стиля:

Другие примеры

При вызове с помощью new, значение this нельзя изменить с помощью bind:

При вызове с помощью new значение this нельзя изменить, вызвав функцию как член другого объекта:

В противном случае, если функция имеет «связанное» значение this:

Каждый раз, когда вызывается boundFunction , значением this будет объект, переданный в bind(boundObject).

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

Не используйте bind для установки какого-либо значения this, не связанного с родительским объектом; обычно это неожиданно, и именно поэтому у this такая плохая репутация. Вместо этого рассмотрите возможность передачи значения в качестве аргумента; ето более явно и работает со стрелочными функциями.

Другие примеры

При вызове связанной функции значение this нельзя изменить с помощью call или apply:

При вызове связанной функции значение this нельзя изменить, вызвав функцию как член другого объекта:

В противном случае, если this установлено во время вызова:

Значение this — это объект, переданный в call/apply.

Предупреждение: не используйте call/apply для установки какого-либо значения this, не связанного с родительским объектом; обычно это неожиданно, и именно поэтому у this такая плохая репутация. Вместо этого рассмотрите возможность передачи значения в качестве аргумента; ето более явно и работает со стрелочными функциями.

К сожалению, для this, использование this для слушивателей событий DOM может привести к трудному для понимания коду:

Так не надо:

Я избегаю использования this в таких случаях, как указано выше, а вместо этого использую:

В противном случае, если функция вызывается через родительский объект (parent.func()):

В этом случае функция вызывается как член obj, так как this и будет obj. Это происходит во время вызова, поэтому ссылка теряется, если функция вызывается без родительского объекта или с другим родительским объектом:

someMethod() === obj ложно, потому что someMethod не вызывается в качестве члена obj. Возможно, вы столкнулись с этим, пытаясь сделать что-то вроде этого:

Это не работает, потому что реализация querySelector имеет свое собственное значение this и ожидает, что это будет своего рода узел DOM. Для правильной реализации вышеуказанного:

Интересный факт: не все API используют this для внутренних целей. Такие методы консоли, как console.log были изменены, чтобы избежать ссылок на this, поэтому log не нужно связывать с console.

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

В противном случае, если функция или родительская область находятся в строгом режиме:

В этом случае значение this не определено. ‘use strict’ не требуется в функции, если родительская область находится в строгом режиме (и все модули находятся в строгом режиме).

Предупреждение: не полагайтесь на это. Я имею в виду, что есть более простые способы получить значение undefined.

В противном случае:

В этом случае значение this такое же, как globalThis. Большинство людей (включая меня) называют глобальный объект globalThis, но это не на 100% технически правильно. Матиас Байненс привёл свои объяснения , в том числе, почему это называется, globalThis а не просто global.

Предупреждение: избегайте использования ссылки this на глобальный объект (да, я все еще так его называю). Вместо этого используйте globalThis, что гораздо более явно.

Это все, что я знаю об this.

Автор: Jake Archibald

Источник: web.dev

Редакция: Команда webformyself.

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии запрещены.