Функции и функциональные выражения

Разница между функцией и функциональным выражением - способ вызова

    var sum = function (a, b) {return a + b;} //функциональное выражение
    sum (2,4) // 6

    function sum (a, b) {return a + b;} //функция
    sum (2,4) // 6

Разница между ними в том, что функция обрабатывается интерпретатором в первую очередь, поэтому функцию можно вызвать ещё до того как она была объявлена в коде.
Функциональное выражение, как и прочие переменные, обрабатывается по мере выполнения кода.

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

Переменные  a и b, которые идут в скобках после объявления функции, называются её параметрами. Значения этих переменных, с которыми она вызывается, - это аргументы функции.
Аргументы передаются в параметры функции. Функция обрабатывает значения параметров и возвращает результат туда, откуда была вызвана.

Если параметр не объявлен.

Не все параметры могут иметь значения. Не объявленный параметр воспринимается функцией как undefined.
Для такого параметра можно создавать отдельные условия.
Например, так:

    function sayHi (name, age ) {
         if ( age === undefined) {
            age = 50;
        }
    } 

Можно короче:

    function sayHi (name, age ) {
        age = age || 50;
    }

В js есть встроенные функции.
Math.floor — функция, которая берет переданное ей число, округляет его вниз до ближайшего целого значения и возвращает результат
Math.random - генерирует случайные числа от 0 до 1;
alert, prompt и confirm выводят на экран окно с сообщением.

Функция содержит:
- ключевое слово function
- имя функции
- список параметров
- тело функции - код, который выполняется при её вызове

Локальные переменные - это переменные, которые объявлены внутри функции при помощи ключевого слова var. За пределами функции они не видны.

Задача
Предскажите какое значение возвратит вызов функции multiplicate(5);
Запустите код в консоли и попробуйте объяснить полученный результат

var a = 2;
function multiplicate(number) {
  result = a * number;
  var a = 5;
  return result;
}

multiplicate(5);


Решение: функция умножает два числа а и number. Если значение number определяется при вызове функции, то с а всё не так просто. Первый раз а объявляется как глобальная переменная, второй раз как локальная уже внутри функции, и именно её значение функция должна была бы использовать. Но так как значение это присвоено ниже по коду, чем его использование в умножении, то на момент умножения оно undefined, и его использование в математическом выражении вернёт NaN.

Задача.
Какое значение вернёт вызов функции

"use strict"

function multiplicate(number) {
  a = 2
  result = a * number;
  var a;
  return result;
}

multiplicate(5);


Решение. Директива use strict требует обязательного объявления переменных. То есть вопрос в том, можно ли объявить переменную после того, как ей уже присвоено значение. Ответ - да. Вначале интерпретатор ищет и запоминает все объявления переменных, а уже потом по ходу выполнения скрипта определяет значения этих переменных.


Блоки if/else, switch, for, while, do..while не влияют на область видимости переменных.
При объявлении переменной в таких блоках, она всё равно будет видна во всей функции.

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

Задача
Обязателен ли "else"?
Следующая функция возвращает true, если параметр age больше 18. В ином случае она задаёт вопрос посредством вызова confirm и возвращает его результат.


function checkAge(age) {
  if (age > 18) {
    return true;
  } else {
    // ...
    return confirm('Родители разрешили?');
  }
}


Будет ли эта функция работать как-то иначе, если убрать else? 


Решение
return можно использовать как замена else
То есть так функция будет тоже работать:

 function checkAge(age) {
  if (age > 18) {
    return true;
  } return confirm('Родители разрешили?');

}

Но можно ещё короче:

function checkAge(age) {
 
return (age > 18) ? true : confirm('Родители разрешили?');

}

И ещё короче:

function checkAge(age) {
 
return (age > 18) || confirm('Родители разрешили?');

}

Задача
Напишите функцию pow(x,n), которая возвращает x в степени n.

Решение:

function pow(x, n) {
    return x ** n;
}

** - это возведение в степень источник

Решение через рекурсию:

function pow(x,n) {
    return n <= 0 ? 1 : pow(x,n-1) * x;
}


new Function

Довольно редкий способ вызова функции, но тем не менее возможный.
Имеет вид:

    new Function(params, code)

Например

    var sum = new Function('a,b', ' return a+b; ');

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

P.S. Там ещё что-то про анонимные функции было.
В общем, это функции без имен, которые используются в коде только один раз и повторно использоваться не будут.

P.P.S. Стрелочные функции.
Они определены стандартом ECMAScript 6
Чем они хороши.
Во-первых, намного короче.
Во-вторых, не имеют собственного контекста вызова.

Сравним.

Это - функция

function plus(a, b) {
  return a + b;
}

Это - функциональное выражение

var plus = function(a, b) {
  return a + b;
}



А это - стрелочная функция

var plus = (a, b) => a + b;

Круто же.

В общем виде стрелочная функция выглядит так:

 (parameters) => {statement}

Если параметр только один, можно обойтись без круглых скобок.

var add = x => x + 1;

Если действие в функции только одно, можно обойтись без фигурных скобок тоже.
Если действий несколько, фигурные скобки нужны:

var pushElement = (arr, el1, el2) => {
  arr.push(el1);
  arr.push(el2);
  return arr;
}

pushElement([1],2,3); // [ 1, 2, 3 ]

Использование стрелочной функции в регулярном выражении

var str="abababab";
str.replace(/a/g, x=>x.toUpperCase()); // AbAbAbAb

Продолжение про стрелочные функции здесь