что такое function declaration и function expression
Функциональные выражения
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/function-expressions.
В JavaScript функция является значением, таким же как строка или число.
Как и любое значение, объявленную функцию можно вывести, вот так:
Обратим внимание на то, что в последней строке после sayHi нет скобок. То есть, функция не вызывается, а просто выводится на экран.
Функцию можно скопировать в другую переменную:
Обычные значения, такие как числа или строки, представляют собой данные. А функцию можно воспринимать как действие.
Объявление Function Expression
Существует альтернативный синтаксис для объявления функции, который ещё более наглядно показывает, что функция – это всего лишь разновидность значения переменной.
Он называется «Function Expression» (функциональное выражение) и выглядит так:
Сравнение с Function Declaration
«Классическое» объявление функции, о котором мы говорили до этого, вида function имя(параметры) <. >, называется в спецификации языка «Function Declaration».
Несмотря на немного разный вид, по сути две эти записи делают одно и то же:
Основное отличие между ними: функции, объявленные как Function Declaration, создаются интерпретатором до выполнения кода.
Поэтому их можно вызвать до объявления, например:
А если бы это было объявление Function Expression, то такой вызов бы не сработал:
Это из-за того, что JavaScript перед запуском кода ищет в нём Function Declaration (их легко найти: они не являются частью выражений и начинаются со слова function ) и обрабатывает их.
А Function Expression создаются в процессе выполнения выражения, в котором созданы, в данном случае – функция будет создана при операции присваивания sayHi = function.
Как правило, возможность Function Declaration вызвать функцию до объявления – это удобно, так как даёт больше свободы в том, как организовать свой код.
Можно расположить функции внизу, а их вызов – сверху или наоборот.
Условное объявление функции
В некоторых случаях «дополнительное удобство» Function Declaration может сослужить плохую службу.
Например, попробуем, в зависимости от условия, объявить функцию sayHi по-разному:
А что, если использовать Function Expression?
Оба этих варианта работают правильно, поскольку, в зависимости от условия, создаётся именно та функция, которая нужна.
Анонимные функции
Взглянем ещё на один пример – функцию ask(question, yes, no) с тремя параметрами:
question Строка-вопрос yes Функция no Функция
Она выводит вопрос на подтверждение question и, в зависимости от согласия пользователя, вызывает функцию yes() или no() :
Здесь же обратим внимание на то, что то же самое можно написать более коротко:
Функциональное выражение, которое не записывается в переменную, называют анонимной функцией.
Действительно, зачем нам записывать функцию в переменную, если мы не собираемся вызывать её ещё раз? Можно просто объявить непосредственно там, где функция нужна.
Такого рода код возникает естественно, он соответствует «духу» JavaScript.
new Function
Существует ещё один способ создания функции, который используется очень редко, но упомянем и его для полноты картины.
Он позволяет создавать функцию полностью «на лету» из строки, вот так:
То есть, функция создаётся вызовом new Function(params, code) :
params Параметры функции через запятую в виде строки. code Код функции в виде строки.
Таким образом можно конструировать функцию, код которой неизвестен на момент написания программы, но строка с ним генерируется или подгружается динамически во время её выполнения.
Пример использования – динамическая компиляция шаблонов на JavaScript, мы встретимся с ней позже, при работе с интерфейсами.
Итого
Функции в JavaScript являются значениями. Их можно присваивать, передавать, создавать в любом месте кода.
Между этими двумя основными способами создания функций есть следующие различия:
Function Declaration | Function Expression | |
---|---|---|
Время создания | До выполнения первой строчки кода. | Когда управление достигает строки с функцией. |
Можно вызвать до объявления | Да (т.к. создаётся заранее) | Нет |
Условное объявление в if | Не работает | Работает |
Если нет явной причины использовать Function Expression – предпочитайте Function Declaration.
Сравните по читаемости:
Function Declaration короче и лучше читается. Дополнительный бонус – такие функции можно вызывать до того, как они объявлены.
Используйте Function Expression только там, где это действительно нужно и удобно.
Function Expression
Функция в JavaScript – это не магическая языковая структура, а особого типа значение.
Синтаксис, который мы использовали до этого, называется Function Declaration (Объявление Функции):
Существует ещё один синтаксис создания функций, который называется Function Expression (Функциональное Выражение).
Оно выглядит вот так:
Смысл обоих примеров кода одинаков: «создать функцию и поместить её значение в переменную sayHi «.
Мы можем даже вывести это значение с помощью alert :
В JavaScript функции – это значения, поэтому мы и обращаемся с ними, как со значениями. Код выше выведет строковое представление функции, которое является её исходным кодом.
Но всё же это значение. Поэтому мы можем делать с ним то же самое, что и с любым другим значением.
Мы можем скопировать функцию в другую переменную:
Давайте подробно разберём всё, что тут произошло:
Заметим, что мы могли бы использовать и Function Expression для того, чтобы создать sayHi в первой строке:
Результат был бы таким же.
У вас мог возникнуть вопрос: Почему в Function Expression ставится точка с запятой ; на конце, а в Function Declaration нет:
Функции-«колбэки»
Рассмотрим ещё примеры функциональных выражений и передачи функции как значения.
Давайте напишем функцию ask(question, yes, no) с тремя параметрами:
question Текст вопроса yes Функция, которая будет вызываться, если ответ будет «Yes» no Функция, которая будет вызываться, если ответ будет «No»
Наша функция должна задать вопрос question и, в зависимости от того, как ответит пользователь, вызвать yes() или no() :
Аргументы функции ask ещё называют функциями-колбэками или просто колбэками.
Ключевая идея в том, что мы передаём функцию и ожидаем, что она вызовется обратно (от англ. «call back» – обратный вызов) когда-нибудь позже, если это будет необходимо. В нашем случае, showOk становится колбэком’ для ответа «yes», а showCancel – для ответа «no».
Мы можем переписать этот пример значительно короче, используя Function Expression:
Подобный код, появившийся в нашем скрипте выглядит очень естественно, в духе JavaScript.
Обычные значения, такие как строки или числа представляют собой данные.
Функции, с другой стороны, можно воспринимать как «действия».
Мы можем передавать их из переменной в переменную и запускать, когда захотим.
Function Expression в сравнении с Function Declaration
Давайте разберём ключевые отличия Function Declaration от Function Expression.
Во-первых, синтаксис: как определить, что есть что в коде.
Function Declaration: функция объявляется отдельной конструкцией «function…» в основном потоке кода.
Function Expression: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части «выражения присваивания» = :
Более тонкое отличие состоит, в том, когда создаётся функция движком JavaScript.
Function Expression создаётся, когда выполнение доходит до него, и затем уже может использоваться.
После того, как поток выполнения достигнет правой части выражения присваивания let sum = function… – с этого момента, функция считается созданной и может быть использована (присвоена переменной, вызвана и т.д. ).
С Function Declaration всё иначе.
Function Declaration можно использовать во всем скрипте (или блоке кода, если функция объявлена в блоке).
Другими словами, когда движок JavaScript готовится выполнять скрипт или блок кода, прежде всего он ищет в нём Function Declaration и создаёт все такие функции. Можно считать этот процесс «стадией инициализации».
И только после того, как все объявления Function Declaration будут обработаны, продолжится выполнение.
В результате, функции, созданные, как Function Declaration могут быть вызваны раньше своих определений.
Например, так будет работать:
Функция sayHi была создана, когда движок JavaScript подготавливал скрипт к выполнению, и такая функция видна повсюду в этом скрипте.
…Если бы это было Function Expression, то такой код вызвал бы ошибку:
Ещё одна важная особенность Function Declaration заключается в их блочной области видимости.
В строгом режиме, когда Function Declaration находится в блоке <. >, функция доступна везде внутри блока. Но не снаружи него.
Такой код, использующий Function Declaration, работать не будет:
Это произошло, так как объявление Function Declaration видимо только внутри блока кода, в котором располагается.
Вот ещё один пример:
Такой код работает, как ожидалось:
Как правило, если нам понадобилась функция, в первую очередь нужно рассматривать синтаксис Function Declaration, который мы использовали до этого. Он даёт нам больше свободы в том, как мы можем организовывать код. Функции, объявленные таким образом, можно вызывать до их объявления.
Также функции вида function f(…) <…>чуть более заметны в коде, чем let f = function(…) <…>. Function Declaration легче «ловятся глазами».
…Но если Function Declaration нам не подходит по какой-то причине (мы рассмотрели это в примере выше), то можно использовать объявление при помощи Function Expression.
Итого
В большинстве случаев, когда нам нужно создать функцию, предпочтительно использовать Function Declaration, т.к. функция будет видима до своего объявления в коде. Это позволяет более гибко организовывать код, и улучшает его читаемость.
Таким образом, мы должны прибегать к объявлению функций при помощи Function Expression в случае, когда синтаксис Function Declaration не подходит для нашей задачи. Мы рассмотрели несколько таких примеров в этой главе, и рассмотрим их ещё больше в будущем.
Function Declaration и Function Expression в JavaScript
Дата публикации: 2016-10-31
От автора: приветствую вас, друзья. Мы продолжаем цикл статей, посвященных изучению JavaScript. И сегодня мы с вами познакомимся с такими понятиями, как Function Declaration и Function Expression в JavaScript, а также узнаем, в чем разница между ними. Приступим.
Собственно, с Function Declaration мы с вами уже знакомы, это стандартное объявление или, иными словами, декларирование функции, которую мы можем вызывать в коде, как после объявления функции, так и до этого:
Оба вызова функции замечательно отработают:
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Хорошо, а что из себя представляет Function Expression? Function Expression (функция выражение, функциональное выражение) — это еще один вариант создания функций, который выглядит следующим образом:
То есть, мы код функции присваиваем обыкновенной переменной. Собственно, переменная в данном случае и будет теперь ни чем иным, как функцией, именем функции, по которому можно к ней обратиться. Давайте попробуем вызвать функцию дважды, как и в предыдущем примере, до объявления функции и после этого:
Упс! Не вышло. Наш код вернул ошибку, сообщая, что функции hello нет. Эта ошибка сработала до объявления функции. Ок, давайте попробуем закомментировать первый вызов функции:
А вот второй вызов успешно отработал. Полагаю, вы уже догадались, в чем конкретно заключается отличие Function Declaration от Function Expression. Правильно, при декларировании функции она (функция) создается до выполнения остального кода. Соответственно, к моменту начала выполнения кода все задекларированные функции уже созданы и доступны к использованию.
В случае же с функциональным выражением функции будут создаваться только в момент выполнения кода, а не перед ним. Использование Function Expression часто можно встретить в коде различных библиотек и скриптов, поэтому, если вы увидите запись в переменную некой функции, не удивляйтесь — это Function Expression.
На этом мы завершим данную статью. Если вы хотите больше узнать о JavaScript, тогда рекомендую обратить свое внимание на уроки по JavaScript и отдельный курс по языку JavaScript. Удачи!
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Различия между function declaration и function expression в javascript.
Всем привет! В этой статье я хочу рассказать про то, что такое function declaration и function expression в языке программирования JavaScript.
На сайте уже была статья про то, что такое функция, как ее создавать и использовать. Если вы вдруг ее еще не читали, то можете почитать здесь
В той статье рассказывалось про function declaration.
Если вы хотите задать function expression, то вам нужно написать так:
var func = function(a, b) < return a + b; >;
Т.е. мы присваиваем функцию переменной. Обратите внимание, что в конце стоит точка с запятой и это нужно делать всегда, т.к. это уже просто значение переменной, в function declaration точки с запятой ставить не нужно. По сути, если вы не поставите точку с запятой, то, скорее всего, ничего страшного не случится, однако есть такие ситуации, где это может сыграть с вами злую шутку и потом найти эту ошибку будет достаточно сложно.
Теперь поговорим об различиях этих двух объявлений функции.
Function Declaration
function sum() <
alert(‘Сработало!’);
>
Прежде чем читать дальше, подумайте, сработает данная функция или нет, ведь мы сначала вызываем ее, а уже потом пишем саму функцию.
Итак, если вы подумали, то вот правильный ответ: ДА, сработает.
Как же такое возможно?
Ответ очень прост. Дело в том, что прежде, чем выполнять код, интерпретатор проходится по нему и собирает в специальное место все объявления переменных и функций. Получается, что он, интепретатор, уже знает весь исходный код функции и может ее вызвать, даже если она написана ниже по коду.
Function Expression
Здесь все в точности, да наоборот.
var func = function() <
alert(‘Сработало!’);
>;
Про такие функции интепретатор узнает лишь тогда, когда дойдет до нее в коде, поэтому пример выше не сработает. Однако, если написать вызов функции ниже, то все будет работать.
Зачем нужны function expression?
На самом деле они много где применяются, но я приведу здесь банальнейший до безобразия пример.
if(age >= 18) <
var func = function() <
alert(‘Добро пожаловать!’);
>;
> else <
var func = function() <
alert(‘Вам еще рановато!’);
>;
>
Теперь, в зависимости от условия, в переменную func будет записан разный исходный код и, следовательно, функции будут вести себя по-разному.
С function declaration такой фокус не пройдет.
if(age >= 18) <
function func() <
alert(‘Добро пожаловать!’);
>
> else <
function func() <
alert(‘Вам еще рановато!’);
>
>
Вот вам еще одна задачка. Подумайте, что будет делать код выше и какой alert(какая функция) сработает в итоге.
Интерпретатор смотрит код сверху вниз, следовательно, он запишет значение последней функции и ее и будет вызывать.
Итак, надеюсь, вы поняли различия между этими 2-мя объявлениями функций.
Спасибо за внимание и удачи в кодинге!
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 0 ):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.
Функции
Функции в JavaScript
Это определяет высокую выразительную мощность JavaScript и позволяет относить его к числу языков, реализующих функциональную парадигму программирования (что само по себе есть очень круто по многим соображениям).
Функция в JavaScript специальный тип объектов, позволяющий формализовать средствами языка определённую логику поведения и обработки данных.
Для понимания работы функций необходимо (и достаточно?) иметь представление о следующих моментах:
Объявление функций
Функции вида «function declaration statement»
Объявление функции (function definition, или function declaration, или function statement) состоит из ключевого слова function и следующих частей:
Например, следующий код объявляет простую функцию с именем square:
Функция square принимает один параметр, названный number. Состоит из одной инструкции, которая означает вернуть параметр этой функции (это number ) умноженный на самого себя. Инструкция return указывает на значение, которые будет возвращено функцией.
Примитивные параметры (например, число) передаются функции значением; значение передаётся в функцию, но если функция меняет значение параметра, это изменение не отразится глобально или после вызова функции.
Если вы передадите объект как параметр (не примитив, например, массив или определяемые пользователем объекты), и функция изменит свойство переданного в неё объекта, это изменение будет видно и вне функции, как показано в следующим примере:
Функции вида «function definition expression»
Функция вида «function declaration statement» по синтаксису является инструкцией (statement), ещё функция может быть вида «function definition expression». Такая функция может быть анонимной (она не имеет имени). Например, функция square может быть вызвана так:
Однако, имя может быть и присвоено для вызова самой себя внутри самой функции и для отладчика (debugger) для идентифицированные функции в стек-треках (stack traces; «trace» — «след» / «отпечаток»).
В следующим коде наша функция принимает функцию, которая является function definition expression, и выполняет его для каждого элемента принятого массива вторым аргументом.
Функция возвращает: [0, 1, 8, 125, 1000].
В JavaScript функция может быть объявлена с условием. Например, следующая функция будет присвоена переменной myFunc только, если num равно 0:
Метод — это функция, которая является свойством объекта. Узнать больше про объекты и методы можно по ссылке: Работа с объектами.
Вызовы функций
Объявление функции не выполняет её. Объявление функции просто называет функцию и указывает, что делать при вызове функции.
Эта инструкция вызывает функцию с аргументом 5. Функция вызывает свои инструкции и возвращает значение 25.
Функции могут быть в области видимости, когда они уже определены, но функции вида «function declaration statment» могут быть подняты (поднятие — hoisting), также как в этом примере:
Область видимости функции — функция, в котором она определена, или целая программа, если она объявлена по уровню выше.
Примечание: Это работает только тогда, когда объявлении функции использует вышеупомянутый синтаксис (т.е. function funcName()<> ). Код ниже не будет работать. Имеется в виду то, что поднятие функции работает только с function declaration и не работает с function expression.
Аргументы функции не ограничиваются строками и числами. Вы можете передавать целые объекты в функцию. Функция show_props() (объявленная в Работа с объектами) является примером функции, принимающей объекты аргументом.
Функция может вызвать саму себя. Например, вот функция рекурсивного вычисления факториала:
Затем вы можете вычислить факториалы от одного до пяти следующим образом:
Область видимости функций
Переменные объявленные в функции не могут быть доступными где-нибудь вне этой функции, поэтому переменные (которые нужны именно для функции) объявляют только в scope функции. При этом функция имеет доступ ко всем переменным и функциям, объявленным внутри её scope. Другими словами функция объявленная в глобальном scope имеет доступ ко всем переменным в глобальном scope. Функция объявленная внутри другой функции ещё имеет доступ и ко всем переменным её родительской функции и другим переменным, к которым эта родительская функция имеет доступ.
Scope и стек функции
Рекурсия
Функция может вызывать саму себя. Три способа такого вызова:
Для примера рассмотрим следующие функцию:
Внутри функции (function body) все следующие вызовы эквивалентны:
Функция, которая вызывает саму себя, называется рекурсивной функцией (recursive function). Получается, что рекурсия аналогична циклу (loop). Оба вызывают некоторый код несколько раз, и оба требуют условия (чтобы избежать бесконечного цикла, вернее бесконечной рекурсии). Например, следующий цикл:
можно было изменить на рекурсивную функцию и вызовом этой функции:
Однако некоторые алгоритмы не могут быть простыми повторяющимися циклами. Например, получение всех элементов структуры дерева (например, DOM) проще всего реализуется использованием рекурсии:
Также возможно превращение некоторых рекурсивных алгоритмов в нерекурсивные, но часто их логика очень сложна, и для этого потребуется использование стека (stack). По факту рекурсия использует stack: function stack.
Поведение стека можно увидеть в следующем примере:
Вложенные функции (nested functions) и замыкания (closures)
Вы можете вложить одну функцию в другую. Вложенная функция (nested function; inner) приватная (private) и она помещена в другую функцию (outer). Так образуется замыкание (closure). Closure — это выражение (обычно функция), которое может иметь свободные переменные вместе со средой, которая связывает эти переменные (что «закрывает» («close») выражение).
Поскольку вложенная функция это closure, это означает, что вложенная функция может «унаследовать» (inherit) аргументы и переменные функции, в которую та вложена. Другими словами, вложенная функция содержит scope внешней («outer») функции.
Следующий пример показывает вложенную функцию:
Поскольку вложенная функция формирует closure, вы можете вызвать внешнюю функцию и указать аргументы для обоих функций (для outer и innner).
Сохранение переменных
Это не отличается от хранения ссылок в других объектах, но часто менее очевидно, потому что не устанавливаются ссылки напрямую и нельзя посмотреть там.
Несколько уровней вложенности функций (Multiply-nested functions)
Функции можно вкладывать несколько раз, т.е. функция (A) хранит в себе функцию (B), которая хранит в себе функцию (C). Обе функции B и C формируют closures, так B имеет доступ к переменным и аргументам A, и C имеет такой же доступ к B. В добавок, поскольку C имеет такой доступ к B, который имеет такой же доступ к A, C ещё имеет такой же доступ к A. Таким образом closures может хранить в себе несколько scope; они рекурсивно хранят scope функций, содержащих его. Это называется chaining (chain — цепь; Почему названо «chaining» будет объяснено позже)
Рассмотрим следующий пример:
Конфликты имён (Name conflicts)
Когда два аргумента или переменных в scope у closure имеют одинаковые имена, происходит конфликт имени (name conflict). Более вложенный (more inner) scope имеет приоритет, так самый вложенный scope имеет наивысший приоритет, и наоборот. Это цепочка областей видимости (scope chain). Самым первым звеном является самый глубокий scope, и наоборот. Рассмотрим следующие:
Замыкания
Closures это один из главных особенностей JavaScript. JavaScript разрешает вложенность функций и предоставляет вложенной функции полный доступ ко всем переменным и функциям, объявленным внутри внешней функции (и другим переменным и функции, к которым имеет доступ эта внешняя функция).
Однако, внешняя функция не имеет доступа к переменным и функциям, объявленным во внутренней функции. Это обеспечивает своего рода инкапсуляцию для переменных внутри вложенной функции.
Также, поскольку вложенная функция имеет доступ к scope внешней функции, переменные и функции, объявленные во внешней функции, будет продолжать существовать и после её выполнения для вложенной функции, если на них и на неё сохранился доступ (имеется ввиду, что переменные, объявленные во внешней функции, сохраняются, только если внутренняя функция обращается к ним).
Closure создаётся, когда вложенная функция как-то стала доступной в неком scope вне внешней функции.
Более сложный пример представлен ниже. Объект с методами для манипуляции вложенной функции внешней функцией можно вернуть (return).
В коде выше переменная name внешней функции доступна для вложенной функции, и нет другого способа доступа к вложенным переменным кроме как через вложенную функцию. Вложенные переменные вложенной функции являются безопасными хранилищами для внешних аргументов и переменных. Они содержат «постоянные» и «инкапсулированные» данные для работы с ними вложенными функциями. Функции даже не должны присваиваться переменной или иметь имя.
Однако есть ряд подводных камней, которые следует учитывать при использовании замыканий. Если закрытая функция определяет переменную с тем же именем, что и имя переменной во внешней области, нет способа снова ссылаться на переменную во внешней области.
Использование объекта arguments
Объект arguments функции является псевдо-массивом. Внутри функции вы можете ссылаться к аргументам следующим образом:
Для примера рассмотрим функцию, которая конкатенирует несколько строк. Единственным формальным аргументом для функции будет строка, которая указывает символы, которые разделяют элементы для конкатенации. Функция определяется следующим образом:
Вы можете передавать любое количество аргументов в эту функцию, и он конкатенирует каждый аргумент в одну строку.
Рассмотрите объект Function в JavaScript-справочнике для большей информации.
Параметры функции
Начиная с ECMAScript 2015 появились два новых вида параметров: параметры по умолчанию (default parameters) и остаточные параметры (rest parameters).
Параметры по умолчанию (Default parameters)
С параметрами по умолчанию проверка наличия значения параметра в теле функции не нужна. Теперь вы можете просто указать значение по умолчанию для параметра b в объявлении функции:
Для более детального рассмотрения ознакомьтесь с параметрами по умолчанию.
Остаточные параметры (Rest parameters)
Остаточные параметры предоставляют нам массив неопределённых аргументов. В примере мы используем остаточные параметры, чтобы собрать аргументы с индексами со 2-го до последнего. Затем мы умножим каждый из них на значение первого аргумента. В этом примере используется стрелочная функция (Arrow functions), о которой будет рассказано в следующей секции.
Стрелочные функции
Более короткие функции
В некоторых функциональных паттернах приветствуется использование более коротких функций. Сравните:
Лексика this
До стрелочных функций каждая новая функция определяла своё значение this (новый объект в случае конструктора, undefined в strict mode, контекстный объект, если функция вызвана как метод объекта, и т.д.). Это оказалось раздражающим с точки зрения объектно-ориентированного стиля программирования.
В ECMAScript 3/5 эта проблема была исправлена путём присвоения значения this переменной, которую можно было бы замкнуть.
В arrow function значением this является окружающий его контекст, так следующий код работает ожидаемо:
Далее
Подробное техническое описание функций в статье справочника Функции
Смотрите также Function в Справочнике JavaScript для получения дополнительной информации по функции как объекту.