Пора признать, что ключевое слово this в javascript — самая загадочная вещь, которая держит нас в ужасе, когда мы встречаемся с JavaScript-интервью. Его поведение было легко понять до того, как появился наш новый друг «⇒» (стрелочные функции), и теперь странное поведение ключевого слова «this» внутри стрелочной функции приводит нас в полное изумление. Итак, давайте преодолеем ужас «этого» и добавим больше любви к Javascript.

Давайте начнем в обратном порядке, сначала я скажу вам ответ, а затем мы попробуем задать несколько вопросов и понять смысл следующих пунктов.

  • Обычные функции (выражение функции и объявление функции) ключевое слово this здесь указывает на объект, вызывающий функцию.
  • Функции со стрелками Ключевое слово this указывает на контекст, в котором определена функция.

Слишком рано, чтобы понять? Просто помните о приведенных выше утверждениях и переходите к нашим вопросам.

Начав с нескольких простых доз, каков будет результат myObj.myNormalFunction()? Правильный ответ 20. Поздравляем!! 🥳, чтобы сделать это правильно. Согласно нашему определению, в myNormalFunction «это» будет указывать на объект, который вызывает эту функцию, то есть myObj, а поскольку myObj является экземпляром MyClass, который имеет свойство «возраст» со значением 20, this.age печатает 20 .

Теперь пришло время поднять нашу сложность 😎, каков будет результат myObj.myArrowFunction()? Опять 20. Но если оба выдают одинаковый результат, значит, разницы нет🤔. Хм, а согласно нашим утверждениям, «эта» внутренняя стрелочная функция будет указывать на контекст, в котором она определена, то есть на MyClass, а поскольку myObj является экземпляром MyClass, она будет указывать на myObj, имеющее свойство age со значением 20.

Выглядит легко сейчас, верно 🥳. Тада!!! время для второго вопроса

Опять тот же вопрос, что будет на выходе myObj.myNormalFunction(). Снова ответ тот же 20, потому что по той же причине, что и для предыдущего вопроса. Но поворот возникает, когда мы пытаемся проверить вывод myObj.myArrowFunction(), он «не определен». Да, так что, как сказано, «это» внутри myArrowFunction будет указывать на контекст, в котором myArrowFunction определено, и поскольку он определен в глобальном контексте, «это» будет указывать на объект window, у которого нет свойства с именем «возраст», поэтому ответ «не определен».

Продолжая нашу игру в догадки, попробуйте угадать вывод следующего:

Таким образом, obj.myNormalFunction() должно напечатать 20, потому что obj вызывает функцию и поскольку она имеет свойство age, следовательно, печатает 20.

Теперь снова настала очередь нашего дьявола😈, что должен напечатать obj.myArrowFunction()? Что ж, ответ «не определено». ПОДОЖДИТЕ, ЧТО!!!🤯. А как насчет нашего определения? Поскольку myArrowFunction определяется внутри obj, не должно ли «this» указывать на контекст, в котором определено myArrowFunction, то есть на obj.? Что ж, теперь нам нужно понять слово «контекст».

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

Итак, поскольку obj — это простой объект (не имеющий собственного контекста), определенный глобально, следовательно, он присутствует в глобальном контексте. Поскольку myArrowFunction определено внутри этого объекта, мы можем сказать, что myArrowFunction также присутствует в глобальном контексте, а «это» указывает на глобальный контекст, который не имеет никакого свойства age, поэтому печатается undefined.

Если в JS есть только два контекста, т. е. функция и глобальный контекст, то как насчет классов, то класс — это просто синтаксический сахар наших обычных функций. Ниже приведен пример, который показывает класс (слева) и его эквивалентный код в функции (справа).

Разве не было загадкой понять такое странное поведение на таких простых примерах? Что ж, поздравляю🎊 с тем, что вы стали настоящим разгадчиком тайн 🧩. Вот очень маленькая загадка снова, чтобы решить для себя. Проверьте приведенный ниже код и попытайтесь объяснить, что должно быть на выходе этого кода в разделе комментариев.