Почему функции?

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

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

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

Функции более высокого порядка
В этом случае функции не просто удобны. Именно здесь функции работают с другими функциями и приносят такую ​​большую мощь, что теперь вы как программист можете делать то, чего не могли делать, когда программа писалась как один огромный фрагмент кода.
Основная идея заключается в том, что функции действуют на функции как на параметры, а не одна функция просто вызывает другую функцию. Одной из идей работы функций в более высоком порядке является рекурсия.

Рекурсия
 — функция определяется с точки зрения самой себя.
 — функция вызывает сама себя.

Почему не следует полагаться на глобальные переменные в своей функции

› var month = ['Янв','Февраль','Мар','Апр'];
undefined
› var getMonth = function (monthNumber ) {
… return month[monthNumber] ;
… };
undefined
› getMonth(1);
'Фев'

Функция getMonth работала нормально, но затем кто-то вошел и изменил массив месяцев. Теперь функция getMonth перестала работать из-за изменения, произошедшего вне ее.

› month = [];
[]
› getMonth(1);
undefined

Локальные переменные инициализируются каждый раз при вызове функции

› var getMonth = function() {
… var months = ['Янв', 'Фев', 'Мар', 'Апр'];
… return months[arguments[0]];
… };
undefined
› getMonth(1);
'Фев'

Хотя эта функция изолирована от каких-либо глобальных изменений, массив месяцев инициализируется каждый раз при вызове функции. Мне просто нужно было знать, какой месяц соответствует номеру 1, и вместо того, чтобы просто читать позицию массива 1, я создаю массив с четырьмя месяцами, а затем читаю месяц в позиции массива 1. Это не так эффективно, как могло бы быть .

Форма закрытия со свойством, согласно которому внутренняя функция имеет доступ к переменным внешней функции даже после выхода из внешней функции

› var getMonth = function() {
… var month = ['Янв', 'Фев', 'Мар', 'Апр'];
… var getMonth = function (monthNumber) {
….. return month[monthNumber];
….. };
… return getMonth;
… };
undefined
› getMonth()(1) ;
'Фев'
› getMonth()(2);
'Мар'
› var f1 = getMonth();
undefined
› f1 (2);
'март'

Это, вероятно, требует немного более пристального внимания, чем может показаться на первый взгляд.
1) Во внешней функции вы определяете массив месяцев.
2) У вас есть внутренняя функция, которая возвращает элемент в этом массиве. index.
3) Когда тогда внешняя функция возвращает внутреннюю функцию при вызове. Обратите внимание, что внешняя функция возвращает не вычисление внутренней функции, а только внутреннюю функцию.
4) Повторяю, внешняя функция не возвращает название месяца. Вместо этого он возвращает функцию, которая может принимать число в качестве параметра и возвращать название месяца.
5) Вызов происходит следующим образом: getMonth()(1)
6) Если это происходит так, будет вызываться каждый раз, тогда как часть выполнения внешней функции будет инициализирован массив цифр, который является локальной переменной во внешней функции. В этом случае эффективность вызова функции getMonth через замыкание не повышается.
7) Однако мы можем записать внутреннюю функцию, возвращаемую внешней функцией, в переменную и вызывать ее несколько раз с разными значениями. значение аргумента. В этом функция выигрывает, потому что инициализация массива месяцев происходит не при каждом вызове, а только один раз, и это тоже в защищенном закрытии, которое никто не видит.
8) Чтобы снова увидеть это волшебство, здесь снова идет фрагмент вызова.

› var f1 = getMonth();
undefined
› f1(2);
'март'
› f1(1);
'февраль'
> › f1(0);
'январь'
› f1(1);
'февраль'

Шаблон условного закрытия для предотвращения инициализации, если инициализация требует больших затрат и функция может никогда не быть вызвана.

Таким образом, инициализация может быть дорогостоящей.
И функция может вообще никогда не использоваться, и в этом случае дорогостоящая инициализация будет пустой тратой времени.
Справедливые опасения. Итак, давайте посмотрим на решение.

› var getMonth = function() {
… var months;
… var getMonth = function ( monthNumber ) {
….. if(!months) {
……. месяцы = ['январь', 'февраль','март','апр'];
……. }
….. return month[monthNumber];
….. }
… return getMonth;
… };
undefined
› var f1 = получитьМесяц();

› f1(1);
‘февраль’
› f1(2);
‘март’

Это решение, и отличие здесь в том, что массив с именами месяцев инициализируется только в том случае, если он еще не был инициализирован. Таким образом, для случая, когда функция никогда не вызывается, массив месяцев в этом случае не инициализируется. И для случая, когда на самом деле существует гораздо более сложная инициализация с участием нескольких серверов баз данных, работающих в диагональных углах мира, тогда да, этот шаблон позволяет всему этому не происходить вообще, если функция аварийной обработки, которой никогда не приходилось вызывать так как ЧП никогда не было.