Возможно, вы не знаете, что это одно из основных различий между обычными функциями и стрелочными функциями ES6 в JavaScript.
Когда я был в учебном лагере по программированию, изучая JavaScript и ES6, казалось, что у всех в классе была некоторая путаница по поводу обычных объявлений функций и новых объявлений функций стрелок ES6. Общие вопросы, которые мы включили:
- Когда нам следует использовать обычные функции или стрелочные функции?
- В чем разница между обычными функциями и стрелочными функциями?
- Можем ли мы использовать одно или другое во всех ситуациях для единообразия?
Проведя небольшое исследование, я обнаружил, что обычные функции и стрелочные функции фактически не взаимозаменяемы в определенных обстоятельствах. Помимо синтаксиса, обычные функции и стрелочные функции имеют еще одно важное отличие: способ связывания ключевого слова this
в JavaScript.
Давайте посмотрим на очень простой пример. Предположим, у нас есть простой объект JavaScript:
У нас есть print
метод на obj1
, который записывает строку в консоль. В результате мы ожидали, что this
в методе print
относится к самому obj1
.
Теперь давайте создадим еще один объект немного другим print
методом:
Теперь метод print
регистрирует результирующую строку только через одну секунду из-за setTimeout
. Но почему он регистрирует undefined is undefined
вместо Object 2 is blue
?
Ответ заключается в объявлении функции, которое мы передали как обратный вызов для setTimeout
. Обычное объявление функции создает область действия, и любое использование this
внутри функции будет относиться к непосредственному родительскому объекту, которому принадлежит функция.
В нашем фрагменте кода в строке 5 анонимная функция, объявленная с использованием обычного объявления функции, передается как обратный вызов для setTimeout
. Затем два this
в строке 6 будут ссылаться на объект, которому принадлежит метод setTimeout
, который оказывается объектом window
.
Поскольку свойства fullName
и color
не существуют в объекте window
, результирующая строка возвращает undefined is undefined
.
Как мы можем сделать так, чтобы два this
в строке 6 вместо этого ссылались на obj2
? На этот раз давайте объявим функцию обратного вызова в строке 5, используя объявление функции стрелки ES6:
Оно работает! Так какова теория этого изменения?
Что ж, оказывается, что объявление функции стрелки создает то, что мы называем лексической областью действия. Это означает, что два this
в строке 6 будут ссылаться не на их непосредственный родительский объект, а на вызывающего, который вызвал функцию, которая их содержит.
В строке 11, когда obj2
вызывает метод print
, любые this
, заключенные внутри стрелочных функций в методе print
, будут ссылаться на obj2
.
Заключение
Я надеюсь, что эта статья хорошо объяснила эти концепции и помогла облегчить некоторую путаницу, которую испытала наша когорта во время учебного лагеря. Ключевое слово this
в JavaScript - это отдельная тема, о которой много говорят в Интернете, но MDN doc здесь является хорошей отправной точкой.