оригинал:Что такое «это» в JavaScript?
Если вы когда-либо работали с библиотекой JavaScript, возможно, вы заметили библиотеку под названиемthis
конкретные ключевые слова. несмотря на то чтоthis
Очень распространен в JavaScript, но полностью понятенthis
Принцип ключевых слов и то, как их использовать в коде, действительно сложен для значительного числа разработчиков. В этой статье я помогу вам понятьthis
и его рабочий механизм.
Прежде чем начать, убедитесь, что вы установилиNode. Затем откройте терминал командной строки и запуститеnode
Заказ.
«это» в глобальной среде
Механизм работы этого не очень легко понять. Мы проходимthis
При разных обстоятельствах понимать отдельноthis
как это работает. Первый взглядglobal
окружающая обстановка.
В глобальной среде,this
Эквивалент глобального объектаglobal
.
> this === global
true
но это толькоnode
эффективен только в. Если мы запустим тот же код в js-файле, результат будет ложным.
Если вы хотите проверить эффект, вы можете создатьindex.js
файл, содержащий следующий код:
console.log(this === global);
затем используйтеnode
Команда для запуска этого файла:
$ node index.js
false
Причина в том, что в файле JavaScript это эквивалентноmodule.exports
вместоglobal
.
"это" в функции
в функцииthis
Значение обычно определяется вызывающей стороной функции. Таким образом, каждый раз, когда функция выполняется,this
Значения могут варьироваться.
существуетindex.js
файл, напишите очень простую функцию для проверкиthis
Равен ли онglobal
объект.
function rajat() {
console.log(this === global)
}
rajat()
если мы используемnode
Запустив этот код, вывод будет true. Если вы добавите в начало файла"use strict"
, и запустите его снова, вы получите ложный вывод, потому что значение this теперь не определено.
Чтобы объяснить это дальше, давайте создадим простую функцию, которая определяет настоящее имя супергероя и имя героя.
function Hero(heroName, realName) {
this.realName = realName;
this.heroName = heroName;
}
const superman= Hero("Superman", "Clark Kent");
console.log(superman);
Обратите внимание, что эта функция не начинается сстрогий режимнаписано.node
Запуск этого кода не дает нам ожидаемых «Супермена» и «Кларка Кента», а просто дает нам неопределенный файл .
Причина этого в том, что, поскольку функция не начинается сстрогий режимнаписанный,this
Указывает на глобальный объект.
если встрогий режимЕсли мы запустим этот код ниже, мы получим ошибку, потому что JavaScript не позволяет атрибутамrealName
а такжеheroName
назначатьundefined
. На самом деле это хорошо, потому что не позволяет нам создавать глобальные переменные.
Кроме того, написание имени функции в верхнем регистре означает, что нам нужно обращаться с ним как с конструктором, используяnew
оператор, чтобы позвонить. Замените последние две строки приведенного выше фрагмента следующим кодом:
const superman = new Hero("Superman", "Clark Kent");
console.log(superman);
бежать сноваnode index.js
команда и теперь получит ожидаемый результат.
"это" в конструкторе
JavaScript не имеет конкретного конструктора. Все, что мы можем сделать, это использоватьnew
Оператор преобразует вызов функции в вызов конструктора, как показано в предыдущем разделе.
При вызове конструктора создается новый объект, которому присваивается значение функции.this
параметр. Конструктор неявно возвращает этот объект, если мы явно не возвращаем другой объект.
существуетhero
Внутри функции добавьте следующееreturn
Заявление:
return {
heroName: "Batman",
realName: "Bruce Wayne",
};
Если мы снова побежимnode
команда, мы увидим上面的
Оператор return переопределяет вызов конструктора.
Единственный случай, когда оператор return не переопределяет вызов конструктора, — это если оператор return не возвращает объект. В этом случае объект будет содержать примитивные значения.
"это" в методе
Когда функция вызывается как метод объекта, объектом является точка this, также известная как вызов функции-получателя (Receiver).
Предполагая, что у объекта-героя есть метод диалога, значение this в диалоге указывает на самого героя. Герой в этот момент также известен как получатель вызова метода диалога.
const hero = {
heroName: "Batman",
dialogue() {
console.log(`I am ${this.heroName}!`);
}
};
hero.dialogue();
Этот пример очень прост, но на практике нашему методу сложно отследить получателя. Добавьте следующий фрагмент кода в конец index.js.
const saying = hero.dialogue;
saying();
Если я сохраню ссылку на диалог в другой переменной и вызову эту переменную как функцию. node запускает код, это вернет undefined, потому что метод потерял приемник. теперь это указывает на global , а не на hero .
Когда мы передаем метод как обратный вызов другому методу, мы обычно теряем получателя. Мы можем исправить это, добавив функцию-оболочку или используя метод привязки для привязки этого к определенному объекту.
вызов() и применение()
Хотя значение this функции устанавливается неявно, мы также можем явно установить этот параметр при вызове функции с помощью call() и apply().
Давайте рефакторим фрагмент кода из предыдущей главы следующим образом:
function dialogue () {
console.log (`I am ${this.heroName}`);
}
const hero = {
heroName: 'Batman',
};
Чтобы использовать объект героя в качестве получателя функции диалога, мы можем использовать call() или apply() следующим образом:
dialogue.call(hero)
// or
dialogue.apply(hero)
Если вы используете call или apply в нестрогом режиме, движок JavaScript будет игнорировать null или undefined, переданные для call или apply. Это одна из причин, по которой рекомендуется всегда писать код в строгом режиме.
bind()
Когда мы передаем метод в качестве функции обратного вызова в другую функцию, всегда существует риск потери исходного получателя метода, из-за чего параметр this указывает на глобальный объект.
Метод bind() может навсегда привязать этот параметр к значению. В приведенном ниже фрагменте кода bind создает новую диалоговую функцию с этим значением, установленным на hero. (Примечание переводчика: метод bind() создаст новую функцию, называемую связанной функцией-связанной функцией-BF. Когда эта связанная функция вызывается, связанная функция будет использовать первое значение, переданное методу bind(), когда оно было В качестве этого используется один параметр, второй и последующие параметры, переданные в метод bind(), а также параметры самой среды выполнения функции привязки используются в качестве параметров исходной функции для вызова исходной функции.)
const hero = {
heroName: "Batman",
dialogue() {
console.log(`I am ${this.heroName}`);
}
};
setTimeOut(hero.dialogue.bind(hero), 1000);
В этом случае значение this нельзя изменить даже с помощью методов call или apply.
"это" в стрелочных функциях
Эти внутренние стрелочные функции сильно отличаются от других типов функций JavaScript. Стрелочная функция использует значение this из окружающего контекста выполнения, поскольку у нее есть собственное значение.
Стрелочные функции фиксируют это значение постоянно, предотвращая его изменение в дальнейшем при применении или вызове.
Чтобы объяснить, как это работает в стрелочных функциях, давайте напишем стрелочную функцию:
const batman = this;
const bruce = () => {
console.log(this === batman);
};
bruce();
Здесь мы сохраняем это значение в переменной, а затем сравниваем это значение со значением this внутри функции стрелки. Запустите node index.js в терминале, вывод должен быть true.
Значение this внутри стрелочной функции не может быть задано явно. Кроме того, использование таких методов, как call, apply или bind для передачи значения this, будет игнорироваться стрелочными функциями. Стрелочные функции относятся к этому значению, установленному стрелочной функцией при ее создании. (Примечание переводчика: в стрелочной функции нет привязки this, и ее значение должно быть определено путем поиска по цепочке областей видимости. Если стрелочная функция обернута нестрелочной функцией, то значение this определяется ближайшим нестрелочная функция на периферии, иначе она не определена.)
Стрелочные функции также нельзя использовать в качестве конструкторов. Следовательно, мы также не можем устанавливать свойства для этих внутренних стрелочных функций.
Так что же могут сделать с этим стрелочные функции?
Стрелочные функции позволяют нам получить доступ к этому в функции обратного вызова. Посмотрите, как это делается с помощью объекта счетчика ниже:
const counter = {
count: 0,
increase() {
setInterval(function() {
console.log(++this.count);
}, 1000);
}
}
counter.increase();
Запуск этого кода с узлом index.js получает только список NaN. Это связано с тем, что this.count больше не указывает на объект счетчика. На самом деле он указывает на глобальный объект.
Если вы хотите, чтобы счетчик работал правильно, вы можете переписать его, используя стрелочные функции.
const counter = {
count: 0,
increase () {
setInterval (() => {
console.log (++this.count);
}, 1000);
},
};
counter.increase();
Функция обратного вызова привязана к методу увеличения, используя это, и теперь счетчик работает нормально.
Примечание. Не записывайте ++this.count как this.count + 1. Последний будет увеличивать значение count только один раз, и каждая итерация будет возвращать одно и то же значение.
"это" в классе
Классы — самая важная часть приложения JavaScript. Давайте посмотрим, как это отличается в классе.
Классы обычно содержат конструктор, и он может указывать на любой вновь созданный объект.
Однако при использовании в качестве метода это также может указывать на любое другое значение, если метод вызывается как обычная функция. Как и методы, классы могут терять своих получателей.
Мы преобразовали созданную ранее функцию Hero в класс. Этот класс содержит конструктор и метод dialog(). Наконец, создайте экземпляр класса и вызовите метод диалога.
class Hero {
constructor(heroName) {
this.heroName = heroName;
}
dialogue() {
console.log(`I am ${this.heroName}`)
}
}
const batman = new Hero("Batman");
batman.dialogue();
Это в конструкторе относится к вновь созданному экземпляру класса. Когда мы вызываем batman.dialogue(), dialog() вызывается как метод, а batman является его получателем.
Но если мы сохраним ссылку на метод dialog() и вызовем его позже как функцию, мы потеряем получателя метода, а параметр this теперь указывает на undefined .
const say = batman.dialogue;
say();
Причина ошибки в том, что классы JavaScript неявно выполняются в строгом режиме. Мы вызываем функцию say() без какой-либо автоматической привязки. Чтобы исправить это, нам нужно вручную связать функцию dialog() с batman, используя bind().
const say = batman.dialogue.bind(batman);
say();
Мы также можем сделать эту привязку в методе конструктора.
Суммировать
Нам нужно использовать это в JavaScript, точно так же, как нам нужно использовать местоимения в английском языке. Возьмем, к примеру, эти два предложения:
- Rajat loves DC Comics.
- Rajat also loves Marvel movies.
Мы можем использовать местоимения, чтобы объединить эти два предложения, так что два предложения теперь становятся:
Rajat loves DC Comics, and he also loves Marvel Comics
Этот короткий урок грамматики прекрасно объясняет этоthis
Важность в JavaScript. Точно так же, как местоимение он соединяет два предложения вместе,this
Может использоваться как ярлык для повторной ссылки на тот же контент.
Надеюсь, эта статья поможет вам ответить на некоторые вопросы о JavaScript.this
Путать, легко ориентироваться по этому простому, но очень важному ключевому слову.
Технологический еженедельник IVWEBШок в сети, обратите внимание на публичный номер: сообщество IVWEB, регулярно каждую неделю публикуйте качественные статьи.