حلقة for في JavaScript (Node.js): دليل شامل
Функция — это сердце программирования. Если переменные — это данные, то функции — это действия. Они позволяют упаковать несколько строк кода в один именованный блок и вызывать его снова и снова. В этом уроке вы поймёте, зачем нужны функции, как их создавать, и откроете для себя магию стрелочных функций и колбэков.
Что такое функция? Аналогия с рецептом
Представьте кулинарную книгу. В ней есть рецепт борща: "взять свёклу, картошку, капусту, сварить, добавить специи..." Каждый раз, когда вы хотите борщ, вы не изобретаете рецепт заново — вы открываете страницу и следуете инструкции.
Функция в программировании — это exactly рецепт. Один раз написали инструкцию — и можете применять её сколько угодно раз:
- Имя функции — как название рецепта ("Борщ")
- Параметры — "пустые поля" в рецепте ("добавить N граммов соли" — N можно менять)
- Тело функции — сам рецепт, последовательность действий
- Возвращаемое значение — результат (готовое блюдо)
Зачем это нужно? Главный принцип программирования — DRY: Don't Repeat Yourself (Не повторяй себя). Если один и тот же код встречается в нескольких местах — выносите его в функцию.
Объявление функции
// Объявление функции (Function Declaration):
function поздороваться() {
console.log("Привет!");
console.log("Как дела?");
}
// Вызов функции (несколько раз!):
поздороваться(); // Привет! Как дела?
поздороваться(); // Привет! Как дела?
поздороваться(); // Привет! Как дела?
Разбор синтаксиса:
function— ключевое слово, говорим JavaScript: "Я объявляю функцию"поздороваться— имя функции (придуманное нами). Правила именования такие же как у переменных()— круглые скобки. В них будут параметры (пока пусто){ ... }— фигурные скобки. Внутри — тело функции, код, который будет выполнятьсяпоздороваться()— вызов функции. Скобки обязательны!
Параметры и аргументы
Параметр — это "пустое поле в рецепте". При вызове функции мы заполняем это поле конкретным значением (аргументом).
// Функция с одним параметром:
function поздороватьсяС(имя) { // имя — параметр (пустое поле)
console.log(`Привет, ${имя}!`);
}
поздороватьсяС("Маша"); // аргумент "Маша" заполняет параметр имя
поздороватьсяС("Петя");
поздороватьсяС("Мир");
// Вывод:
// Привет, Маша!
// Привет, Петя!
// Привет, Мир!
// Функция с несколькими параметрами:
function сложить(а, б) {
console.log(`${а} + ${б} = ${а + б}`);
}
сложить(5, 3); // 5 + 3 = 8
сложить(10, 20); // 10 + 20 = 30
сложить(1, 1); // 1 + 1 = 2
Важное отличие понятий: параметр — это имя в объявлении функции (function f(параметр)). Аргумент — это конкретное значение при вызове (f(аргумент)). Часто эти слова используют как синонимы, но строго говоря — они разные.
Параметры по умолчанию
// Если аргумент не передан — используется значение по умолчанию:
function приветствие(имя = "незнакомец", время = "день") {
console.log(`Добрый ${время}, ${имя}!`);
}
приветствие("Коля", "вечер"); // Добрый вечер, Коля!
приветствие("Таня"); // Добрый день, Таня! (время = "день" по умолчанию)
приветствие(); // Добрый день, незнакомец! (оба по умолчанию)
Возвращаемое значение: return
Пока наши функции просто что-то делали (выводили в консоль). Но функции могут ещё и возвращать результат — как рецепт, который в итоге даёт готовое блюдо.
// Функция без return только делает что-то (side effect):
function сказатьПривет() {
console.log("Привет!"); // Делает вывод в консоль
}
let результат = сказатьПривет(); // "Привет!" выводится в консоль
console.log(результат); // undefined (функция ничего не вернула)
// Функция с return возвращает значение:
function сложить(а, б) {
return а + б; // ВЕРНУТЬ результат
}
let сумма = сложить(5, 3); // сумма теперь = 8
console.log(сумма); // 8
console.log(сложить(10, 20)); // 30 (можно использовать прямо в выражениях)
// Практичный пример:
function рассчитатьСкидку(цена, процент) {
let скидка = цена * (процент / 100);
let итого = цена - скидка;
return итого;
}
let ценаТовара = 1000;
let цена10 = рассчитатьСкидку(ценаТовара, 10); // 900
let цена25 = рассчитатьСкидку(ценаТовара, 25); // 750
console.log(`Со скидкой 10%: ${цена10} руб.`);
console.log(`Со скидкой 25%: ${цена25} руб.`);
Важно: после выполнения return функция немедленно завершается. Код после return не выполняется:
function тест() {
console.log("Это выполнится");
return 42;
console.log("Это НЕ выполнится"); // Недостижимый код
}
let x = тест(); // В консоли: "Это выполнится"
console.log(x); // 42
Функциональное выражение
Функцию можно записать в переменную — это называется функциональное выражение:
// Function Expression — функция как значение переменной:
const умножить = function(а, б) {
return а * б;
};
console.log(умножить(3, 4)); // 12
console.log(умножить(5, 5)); // 25
// Разница с Function Declaration:
// Function Declaration можно вызвать ДО объявления:
console.log(сложить1(2, 3)); // 5 — работает! (hoisting)
function сложить1(а, б) { return а + б; }
// Function Expression нельзя вызвать до объявления:
// console.log(сложить2(2, 3)); // Ошибка! (ReferenceError)
const сложить2 = function(а, б) { return а + б; };
Стрелочные функции (Arrow Functions)
В ES2015 появился новый, более краткий синтаксис для функций — стрелочные функции. Они выглядят необычно поначалу, но очень удобны.
// Обычная функция:
const сложить = function(а, б) {
return а + б;
};
// То же самое — стрелочная функция:
const сложить = (а, б) => {
return а + б;
};
// Если тело функции — одно выражение, можно ещё короче:
const сложить = (а, б) => а + б;
// Один параметр — скобки не обязательны:
const удвоить = n => n * 2;
// Без параметров — скобки обязательны:
const привет = () => "Привет!";
// Примеры использования:
console.log(сложить(3, 4)); // 7
console.log(удвоить(5)); // 10
console.log(привет()); // Привет!
Зачем придумали стрелочные функции?
Две причины: краткость и поведение this. Краткость очевидна из примеров выше. С this разберёмся в уроке об объектах. Пока запомните: стрелочные функции удобны для коротких операций, особенно в массивах (следующий урок).
// Сравнение записей одной и той же логики:
const числа = [1, 2, 3, 4, 5];
// Длинная запись:
const удвоенные1 = числа.map(function(n) {
return n * 2;
});
// Стрелочная:
const удвоенные2 = числа.map(n => n * 2);
console.log(удвоенные1); // [2, 4, 6, 8, 10]
console.log(удвоенные2); // [2, 4, 6, 8, 10]
Область видимости (Scope)
Область видимости — это "зона", где переменная существует и доступна. Аналогия: переменная, объявленная в комнате, существует только в этой комнате. Из соседней комнаты её не видно.
// Глобальная переменная — видна везде:
let глобальная = "Я глобальная";
function мояФункция() {
// Локальная переменная — видна только внутри функции:
let локальная = "Я локальная";
console.log(глобальная); // "Я глобальная" — видно!
console.log(локальная); // "Я локальная" — видно!
}
мояФункция();
console.log(глобальная); // "Я глобальная" — видно
// console.log(локальная); // ReferenceError — не видно из глобальной зоны!
// Переменная в блоке (if, for, while):
if (true) {
let блочная = "Я в блоке";
console.log(блочная); // "Я в блоке" — видно внутри блока
}
// console.log(блочная); // ReferenceError — не видно вне блока!
// ВАЖНО: var не уважает блоки (ещё одна причина не использовать var):
if (true) {
var старая = "Я var";
}
console.log(старая); // "Я var" — var "утёк" из блока!
Функции-колбэки (Callbacks)
Одна из самых мощных возможностей JavaScript — передавать функции как аргументы другим функциям. Функция, переданная как аргумент, называется callback (колбэк, обратный вызов).
Аналогия: вы оставляете записку другу "когда придёт посылка, позвони мне" — номер телефона это ваш callback. Друг "вызывает вас обратно" в нужный момент.
// Простой пример колбэка:
function выполнить(действие) {
console.log("Начинаем...");
действие(); // Вызываем переданную функцию
console.log("Готово!");
}
function сказатьПривет() {
console.log("Привет!");
}
function сказатьПока() {
console.log("Пока!");
}
выполнить(сказатьПривет); // Начинаем... Привет! Готово!
выполнить(сказатьПока); // Начинаем... Пока! Готово!
// Чаще всего колбэки передают анонимно (без имени):
выполнить(function() {
console.log("Анонимная функция!");
});
// Или через стрелочную функцию:
выполнить(() => console.log("Стрелочный колбэк!"));
Практический колбэк: setTimeout
// setTimeout — выполнить функцию через N миллисекунд:
console.log("Старт");
setTimeout(function() {
console.log("Это выполнится через 2 секунды");
}, 2000); // 2000 миллисекунд = 2 секунды
console.log("Конец");
// Вывод:
// Старт
// Конец
// Это выполнится через 2 секунды (через 2 сек!)
// Стрелочная запись:
setTimeout(() => console.log("Привет через секунду!"), 1000);
Обратите внимание на порядок вывода! "Конец" выводится раньше, чем текст из setTimeout. Это потому что JavaScript не ждёт таймера — он продолжает выполнение и "вспоминает" про setTimeout позже. Это называется асинхронность — подробнее в последнем уроке курса.
IIFE: самовызывающаяся функция
IIFE (Immediately Invoked Function Expression) — функция, которая вызывает себя сама немедленно после объявления. Использовалась для создания изолированной области видимости (до появления модулей):
// Обычная функция — объявляем, потом вызываем:
function обычная() {
console.log("Обычная");
}
обычная();
// IIFE — объявляем и сразу вызываем:
(function() {
let секретнаяПеременная = "Никто снаружи меня не видит";
console.log("IIFE выполнилась!");
console.log(секретнаяПеременная);
})(); // <-- скобки в конце запускают функцию
// Стрелочная IIFE:
(() => {
console.log("Стрелочная IIFE!");
})();
В современном коде IIFE нужны реже, но вы встретите их в старых проектах.
Практический пример: игра "Угадай число"
// Функция для генерации случайного числа:
function случайноеЧисло(мин, макс) {
return Math.floor(Math.random() * (макс - мин + 1)) + мин;
}
// Функция для проверки угадывания:
function проверить(загаданное, угаданное) {
if (угаданное === загаданное) {
return "победа";
} else if (угаданное < загаданное) {
return "больше";
} else {
return "меньше";
}
}
// Основная игра:
function игра() {
const секретноеЧисло = случайноеЧисло(1, 10);
let попыток = 0;
let угадал = false;
while (!угадал && попыток < 5) {
let ввод = prompt(`Угадай число от 1 до 10 (попытка ${попыток + 1}/5):`);
let число = Number(ввод);
попыток++;
let результат = проверить(секретноеЧисло, число);
if (результат === "победа") {
alert(`🎉 Правильно! Ты угадал за ${попыток} попыток!`);
угадал = true;
} else if (результат === "больше") {
alert("Загаданное число больше!");
} else {
alert("Загаданное число меньше!");
}
}
if (!угадал) {
alert(`Не угадал. Загаданное число было ${секретноеЧисло}`);
}
}
игра(); // Запускаем игру!
Это уже настоящая маленькая игра! Обратите внимание, как задача разбита на три функции: одна генерирует число, другая проверяет угадывание, третья управляет игровым процессом. Каждая делает одно дело — это хороший стиль программирования.
Типичные ошибки новичков
- Забыть скобки при вызове.
поздороваться— это ссылка на функцию (не вызов).поздороваться()— вызов функции. Без скобок функция не выполнится. - Не использовать return. Если нужен результат — не забывайте
return. Без него функция вернётundefined. - Код после return. После
returnвыполнение функции заканчивается. Код ниже не выполнится. - Путать параметры и аргументы. Параметр — имя в объявлении. Аргумент — значение при вызове. Путаница в терминах не страшна, но понимать разницу важно.
- Слишком длинные функции. Если функция делает больше одной вещи — разбейте её на несколько. Каждая функция должна делать одно дело.
- Неговорящие имена.
function f(x)vsfunction рассчитатьНалог(сумма). Второй вариант читается как книга.
Итого
В этом уроке мы узнали:
- Функция — именованный блок кода, который можно выполнять многократно.
- Параметры — переменные-"заглушки" в определении функции. Аргументы — конкретные значения при вызове.
- return — возвращает значение из функции. После return функция завершается.
- Параметры по умолчанию — значение, если аргумент не передан.
- Стрелочные функции — краткий синтаксис:
const f = (а, б) => а + б. - Область видимости — переменные внутри функции не видны снаружи.
- Колбэки — функции, переданные как аргументы другим функциям.
- IIFE — самовызывающаяся функция для изоляции кода.
В следующем уроке мы изучим массивы — способ хранить несколько значений в одной переменной.