Функции как значения
Чему вы научитесь:
- передавать функцию аргументом, хранить её в переменной или объекте и возвращать из другой функции;
- объяснять, что такое замыкание и почему переменная живёт после конца вызова;
- предсказывать, что вернут функции, созданные в цикле с
letи сvar; - определять, чему равен
thisв вызове, и возвращать методу его объект черезbindили стрелочную функцию.

Представьте карточку с рецептом. По ней можно приготовить блюдо прямо сейчас. Но карточку можно и отдать другу, положить в коробку с другими рецептами или прикрепить к холодильнику. Готовить по ней будет тот, у кого она окажется, и тогда, когда ему понадобится.
Функция в JavaScript похожа на такую карточку. Имя функции без скобок — сама карточка, а скобки после имени означают «приготовить сейчас». В этой теме карточка будет с нами во всех уроках.
Как вы уже знаете, метод map получает функцию аргументом и сам вызывает её для каждого элемента массива. Функцию, которая работает так же, как map, можно написать и самим. Здесь mapAll делает то же, что map, но массив получает первым параметром:
function mapAll(nums, fn) {
const result = [];
for (const n of nums) {
result.push(fn(n));
}
return result;
}
console.log(mapAll([1, 2, 3], (n) => n * 10)); // [ 10, 20, 30 ]
console.log(mapAll([1, 2, 3], (n) => n % 2 === 0)); // [ false, true, false ]Давайте разберём, что происходит в первом вызове:
mapAllполучает массив[1, 2, 3]и стрелочную функцию(n) => n * 10. Функция лежит в параметреfn, как карточка в руке.- Цикл
for…ofберёт элементы по одному. - Вызов
fn(n)выполняет переданную функцию так же, как вызов по имени, и возвращает её результат. result.pushскладывает результаты в новый массив, и программа печатает[ 10, 20, 30 ].
Функция высшего порядка
Функция mapAll принимает другую функцию. Поэтому она, как и forEach из темы о методах массивов, — функция высшего порядка. Переданная ей стрелочная функция — колбэк.
Работу здесь делят двое:
- функция высшего порядка решает, когда и с какими аргументами вызвать колбэк и что сделать с его результатом;
- колбэк решает, что сделать с одним элементом.
Цикл, который собирает новый массив, написан в mapAll один раз. Для другой задачи меняется только колбэк. В первом вызове он умножает числа на 10, во втором проверяет их на чётность.
Так же устроены forEach, filter и reduce. Обход массива спрятан внутри метода, а действие приходит снаружи.
Что ещё можно делать с функцией
Функция — такое же значение, как число или строка. Раз с функциями можно делать всё то же, что с другими значениями, их называют функциями первого класса. На собеседовании часто спрашивают, что значит «функции в JavaScript — первого класса». Ответ — три действия: функцию можно передать аргументом, сохранить и вернуть из другой функции. Передачу аргументом вы уже видели, осталось два действия.
Сохранить
Функцию можно положить в константу, в элемент массива или в свойство объекта и вызвать оттуда. Это карточка, убранная в коробку: достать её можно в любой момент.
Вернуть
Функцию можно вернуть из другой функции через return. Тогда вызов отдаёт не число и не строку, а готовую карточку. Её можно сохранить, а можно вызвать тут же, поставив после вызова вторые скобки.
Оба действия есть в одном примере:
function pick(sign) {
if (sign === "+") {
return (a, b) => a + b;
}
return (a, b) => a - b;
}
const ops = { plus: pick("+"), minus: pick("-") };
console.log(ops.plus(5, 3), ops.minus(5, 3)); // 8 2
console.log(pick("+")(2, 2)); // 4Разберём по шагам:
pickвозвращает не число, а функцию: сложение для"+"и вычитание для остальных знаков.const ops = { … }сохраняет обе функции в свойствахplusиminusобъектаops.ops.plus(5, 3)достаёт функцию из свойстваplusи вызывает её, а программа печатает8 2.pick("+")(2, 2)сначала получает функцию сложения, а вторые скобки сразу вызывают её с двумя аргументами. Получается4.
Здесь аналогия с карточкой перестаёт работать: бумажную карточку отдают, и у вас её больше нет. Функцию можно положить сразу в десять мест, и все они ведут к одной и той же функции.
Частая ошибка
Функция должна вернуть функцию, а вернула результат вызова:
function double(n) {
return n * 2;
}
function getDouble() {
return double(); // ✗
}
const f = getDouble();
console.log(f(4));TypeError: f is not a functionСкобки после double вызывают её прямо в return, без аргумента, и вызов даёт NaN. Поэтому getDouble возвращает число NaN, а число вызвать нельзя. Это как отдать другу не карточку, а уже приготовленное блюдо. Чтобы вернуть саму функцию, пишите имя без скобок: return double;.
Главное
- Функция — значение: её передают аргументом, хранят в переменной, массиве или объекте и возвращают из другой функции.
- Функция высшего порядка принимает или возвращает другую функцию, а переданная ей функция — колбэк.
- Имя без скобок — сама функция, имя со скобками — её вызов и результат.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.