Функции в JavaScript: как их объявлять, вызывать и использовать без ошибок
Руководство для тех, кто только начинает изучать JavaScript.


Иллюстрация: Polina Vari для Skillbox Media
Функции — один из самых важных инструментов в JavaScript. С их помощью можно структурировать код, переиспользовать логику и делать программу проще для чтения и поддержки. В этой статье разберём, что такое функции, как их правильно объявлять и вызывать, что такое return, this, замыкания и как избежать типичных ошибок.
Содержание
- Зачем вообще нужны функции
- Как устроена функция
- Как объявить функцию
- Как вызвать функцию
- Как передавать данные
- Как вернуть результат из функции: оператор return
- Области видимости: глобальная и локальная
- Объявление функции через function expression
- Стрелочные функции (arrow functions)
- This: как работает контекст выполнения
- Типичные ошибки: как их избежать
- Советы и лайфхаки для работы
Зачем вообще нужны функции
Во многих веб-проектах разработчики выполняют одни и те же действия: проверяют формы, открывают модальные окна, управляют выпадающими меню.
Если каждый раз писать один и тот же код, он начинает дублироваться во всём проекте. Когда нужно внести правку, приходится менять все копии. Это долго, и легко ошибиться, а ещё код становится длиннее и сложнее для чтения.
Функции решают эту проблему. С их помощью можно один раз описать нужное поведение, а потом просто вызывать его в нужных местах. Это удобно, сокращает количество строк и делает код чище.
Такой подход помогает:
- сократить объём кода — не нужно повторять одни и те же фрагменты,
- улучшить читаемость — можно называть действия своими именами,
- упростить сопровождение — правки в одном месте срабатывают везде.
Это особенно важно в JavaScript, где многие интерфейсные действия повторяются десятки раз. Без функций код быстро выходит из-под контроля.
Как устроена функция в JavaScript
Функция — это самостоятельный блок кода, который можно вызывать в любом месте программы. Она может принимать входные данные, выполнять действия и возвращать результат.
Пример простой функции:
function sayHello() {
console.log("Привет!");
}
sayHello();
Здесь:
- мы объявили функцию sayHello();
- написали, что она должна делать, — вывести сообщение в консоль;
- вызвали функцию по имени.
Функция срабатывает, когда мы её вызываем. Если не вызвать, она просто будет существовать в коде без действия.
Формально любая функция в JavaScript проходит три этапа:
- Объявление — создаём функцию и даём ей имя.
- Определение поведения — пишем, что именно она должна делать.
- Вызов — запускаем выполнение по имени с помощью круглых скобок.
Это простой и надёжный способ структурировать код. Вместо того чтобы повторять одно и то же — пишем один раз, вызываем сколько угодно.
Кстати, есть и исключения. Некоторые функции в JavaScript создаются прямо на лету, во время выполнения программ. О них мы расскажем чуть позже.
Как объявить функцию в JavaScript
Чтобы объявить функцию, начните с ключевого слова function, укажите имя, круглые скобки для параметров (даже если их нет), а затем — фигурные скобки с кодом внутри.
function sayHello() {
console.log("Привет, мир!");
}
Этот код создаёт функцию sayHello, которая содержит внутри себя команду console.log("Привет, мир!").
Способ называется function declaration. Он удобен тем, что функцию можно вызывать ещё до её объявления в коде.
Как вызвать функцию в JavaScript
Создать функцию — только половина дела. Чтобы она сработала, её нужно вызвать. То есть сказать программе: «выполни вот это прямо сейчас».
Для этого пишем имя функции и добавляем круглые скобки:
sayHello();
В этот момент JavaScript находит функцию sayHello и запускает всё, что в ней написано. В нашем примере она выводит в консоль сообщение:
Привет, мир!
Запомните: если функцию не вызвать — она ничего не сделает. Она будет просто ждать своего часа в коде.
Как передавать данные в функцию
Часто бывает нужно, чтобы одна и та же функция работала с разными значениями. Например, вы пишете код для сайта интернет-магазина. Покупателю нужно показать приветствие: «Здравствуйте, [имя]». Имя у каждого пользователя своё, и передать его в функцию гораздо удобнее, чем писать для каждого посетителя свой блок кода.
Для этого в функцию можно передавать данные. При её создании мы указываем параметры — это пустые места, в которые потом подставятся нужные значения. А при вызове передаём конкретные данные, которые функция и использует.
function sayHelloName(name) {
console.log("Привет, " + name + "!");
}
sayHelloName("Андрей"); // "Привет, Андрей!"
sayHelloName("Марина"); // "Привет, Марина!"
Здесь name — это параметр функции sayHelloName. При вызове функции мы передаём конкретное значение, которое подставляется вместо name.
Добавление нескольких параметров
Можно передавать сразу несколько параметров. Указываем их через запятую:
function sayHelloFullname(name, surname) {
console.log("Привет, " + name + " " + surname + "!");
}
sayHelloFullname("Андрей", "Иванов"); // "Привет, Андрей Иванов!"
Определение параметра по умолчанию
Не всегда получается передать все значения во время вызова функции. В таких случаях можно задать значение по умолчанию, тогда JavaScript сам подставит нужное значение.
function sayHelloName(name = "гость") {
console.log("Привет, " + name + "!");
}
sayHelloName(); // "Привет, гость!"
sayHelloName("Катя"); // "Привет, Катя!"
Здесь, если функция sayHelloName вызывается без аргумента, параметр name принимает значение "гость".
Значения по умолчанию могут быть не только строками или числами. Это может быть результат выражения или вызова другой функции. Можно, допустим, установить текущую дату и время в качестве значения по умолчанию.
function logEvent(message, timestamp = new Date().toISOString()) {
console.log(`[${timestamp}] ${message}`);
}
logEvent("Неверный логин");
// [2025-02-22T12:34:56.789Z] Неверный логин
logEvent("Ошибка подключения", "2025-01-01T00:00:00Z");
// [2025-01-01T00:00:00Z] Ошибка подключения
Неизвестное количество параметров у функции
Иногда заранее не известно, сколько параметров передастся в функцию. Например, пользователь может выбрать один, два или десять элементов из списка — и все они должны попасть в функцию. В этом случае пригодится оператор ... (rest), который собирает все дополнительные аргументы в массив. Он записывается в виде трёх точек перед нужным параметром.
function sayHelloManynames(...names) {;
let fullName = names.join(" ");
console.log(`Привет, ${fullName}!`); // Объединяет все имена в одну строку с пробелами
}
sayHelloManynames("Омар", "ибн", "аль-Хаттаб", "аль-Фарук");
// Привет, Омар абн аль-Хаттаб аль-Фарук!
Здесь ...names собирает все переданные аргументы в массив names, который затем объединяется в строку с помощью join(" ").
Как вернуть результат из функции: оператор return
Функции в JavaScript могут не только выполнять действия, но и возвращать результат своей работы. Допустим, вы пишете калькулятор. Пользователь вводит два числа, а калькулятору нужно показать сумму. В этом случае удобно создать функцию sum(a, b), которая возвращает результат сложения. Вы передаёте ей значения и получаете ответ, с которым можно работать дальше — например, отобразить его на экране или использовать в других вычислениях.
Для этого используется ключевое слово return. Оператор позволяет функции вернуть значение в то место, из которого она была вызвана. Это полезно, когда необходимо использовать результат вычислений функции в других частях программы.
function greet(name) {
return "Привет, " + name + "!";
}
const message = greet("Марина");
console.log(message); //Выведет: "Привет, Марина!"
Здесь:
- JavaScript выполнит вызов функции greet(), передав ей строку "Марина";
- вернёт полученную строку "Привет, Марина!" и присвоит её переменной message;
- выведет message на печать.
Важно: когда интерпретатор JavaScript встречает return, выполнение функции немедленно прекращается. Код после return внутри функции не будет выполнен.
function greet(name) {
return "Привет, " + name + "!";
console.log("Это сообщение никогда не будет выведено.");
}
Что можно вернуть из функции
Функция может возвращать любое значение:
- строку или число;
- массив;
- объект;
- другую функцию.
function createUser(name, age) {
return {
name: name,
age: age
};
}
console.log(createUser("Тимофей", 25));
// { name: "Тимофей", age: 25 }
Возврат значений часто используется, чтобы создавать структуру данных — например, карточку пользователя, заказ или товар.
Функции без return
Бывают случаи, когда от функции не нужно никакого результата. Она просто что-то делает — например, выводит сообщение, запускает анимацию или меняет содержимое страницы.
В таких функциях можно не использовать return. Они сработают, выполнят действия, и всё.
function greet(name) {
console.log("Привет, " + name + "!");
}
const message = greet("Марина"); // Выведет: «Привет, Марина!»
console.log(message); // Выведет: undefined
Что произойдёт:
- в консоль выведется "Привет, Марина!";
- затем выведется undefined, потому что функция greet() ничего не вернула.
Если в функции нет return, JavaScript автоматически возвращает undefined.
Чем отличается функция, возвращающая значение, от функции без return:
- Если функция использует return, она возвращает указанное значение.
- Если функция не использует return, она по умолчанию возвращает undefined.
Области видимости в функциях JS: глобальная и локальная
В JavaScript область видимости (scope) — это правило, по которому переменные доступны в разных частях кода. Когда мы объявляем переменную, она «живёт» только в определённой зоне. И важно понимать, где именно она будет доступна.
С функциями связаны две основные области видимости: глобальная и локальная.
Глобальная область
Если переменная создана вне функции, она глобальная. Такая переменная доступна в любом месте программы, в том числе внутри функций.
const globalVar = "Я доступна везде!"; // Глобальная переменная
function showVar() {
console.log(globalVar); // Доступ к глобальной переменной внутри функции
}
showVar(); // «Я доступна везде!»
Важно: глобальные переменные легко случайно изменить из разных частей программы. Это может привести к ошибкам, которые трудно отследить.
Локальная область
Если переменная объявлена внутри функции, она локальная. То есть доступна только в этой функции и нигде больше.
function showVar() {
let localVar = «Я доступна в функции!»;
console.log(localVar); // Доступна внутри функции
}
showVar(); // «Я доступна в функции!»
console.log(localVar); // Ошибка! localVar не определена за пределами функции
Почему так: переменная localVar существует только внутри функции showVar. За её пределами она не видна и не может быть использована.
Важно: локальные переменные защищены от изменений извне. Это делает код более предсказуемым и безопасным.
Замыкание в JS: наследование областей видимости
В JavaScript функция может «запоминать» переменные из того места, где она была создана. Даже если вызвать её позже, в другом месте, — она всё равно будет помнить эти значения.
Когда одна функция создаётся внутри другой, внутренняя функция сохраняет доступ ко всем переменным, которые были в момент её создания. Даже если внешняя функция уже завершила работу, эти переменные остаются доступны.
Представьте, что внутренняя функция как будто кладёт переменные в невидимый «рюкзак» и носит с собой:
function createCounter() {
let count = 0; // Переменная из внешней области видимости
return function() {
count++;
console.log("Текущее значение:", count);
}; // Внутренняя функция, имеющая доступ к count
}
const counter = createCounter(); // Создаём функцию-счётчик
counter(); // Текущее значение: 1
counter(); // Текущее значение: 2
counter(); // Текущее значение: 3
Здесь:
- createCounter() создаёт переменную count и возвращает функцию;
- эта функция увеличивает count и выводит его значение;
- даже после завершения createCounter() переменная count не исчезает, — она «живёт» внутри замыкания.
Это и есть замыкание: внутренняя функция «помнит» переменную count, потому что была создана в той же области видимости.
Замыкания удобны, когда нужно, чтобы функция помнила информацию между вызовами. Это может быть полезно в разных ситуациях:
- вы создаёте счётчик, который увеличивается каждый раз, когда вызывается функция;
- пишете обработчик событий, которому нужно помнить, что было раньше;
- хотите сгенерировать уникальные ID и не повторяться;
- хотите спрятать данные от внешнего доступа и не дать другим частям программы их менять.
Во всех этих случаях замыкание помогает сохранить переменные внутри функции, не делая их глобальными.
Объявление функции через function expression
В JavaScript есть два основных способа создать функцию:
- через function declaration — привычное объявление с ключевым словом function;
- Через function expression — функция создаётся внутри выражения и сохраняется в переменную.
Пример:
const greet = function () {
console.log("Привет!");
};
greet();
Такую функцию нельзя вызвать до её создания, потому что переменная, в которую она записана, появляется только в момент выполнения.
Когда это бывает полезно
Допустим, у нас есть условие: если пользователю меньше 18 — одно сообщение, если больше — другое. Мы хотим выбрать подходящую функцию в зависимости от возраста.
const age = Number(prompt("Сколько вам лет?")); // Выводит диалоговое окно с вопросом
let greet; // Объявляем переменную greet, которой затем присвоим значение функции
if (age < 18) {
greet = function() {
alert("Привет!");
};
} else {
greet = function() {
alert("Здравствуйте!");
};
}
greet();
Здесь:
- мы запрашиваем возраст с помощью prompt();
- определяем функцию greet() в зависимости от значения age;
- вызываем greet(), и пользователь получает соответствующее приветствие.
Важно: пример с prompt() и alert() работает только в браузере. В среде Node.js такие функции не поддерживаются.

Читайте также:
Почему не стоит использовать function declaration внутри if
Если попробовать создать функцию обычным способом — function greet() { ... } — прямо внутри if, могут возникнуть проблемы.
В JS есть директива use strict, которая включает строгий режим. Он делает код более безопасным: запрещает некоторые устаревшие конструкции и помогает сразу замечать ошибки.
В строгом режиме такая функция будет существовать только внутри блока if. За пределами блока она будет недоступна — и, если вы попытаетесь её вызвать снаружи, получите ошибку.
Function expression — это способ избежать этой ошибки. Мы сначала создаём переменную, например greet, а потом в нужный момент записываем в неё нужную функцию. Так код работает надёжно и предсказуемо — вне зависимости от условий.
Стрелочные функции (arrow functions) в JavaScript
Стрелочные функции — это короткий способ записать функцию. Их добавили в JavaScript в 2015 году (ES6).
Главное отличие — вместо function используется стрелка =>. Ещё одна особенность: если внутри функции всего одна строка, можно не писать фигурные скобки и return — JavaScript поймёт всё сам.
Пример:
const greet = (name) => `Привет, ${name}!`;
console.log(greet("Анна")); // Выведет: «Привет, Анна!»
Почему это удобно:
- Меньше кода. Особенно для коротких функций, которые делают что-то одно.
- Проще читать. Нет function, нет лишних скобок, — всё ясно с первого взгляда.
- this работает иначе. В стрелочных функциях this не меняется. Это удобно, когда нужно сохранить контекст из внешней области.

Читайте также:
This: как работает контекст выполнения в функциях JavaScript
Когда JavaScript начинает выполнять код, он создаёт для этого специальную «рабочую зону». Эта зона называется контекстом выполнения (или просто контекстом). Она помогает понять, где сейчас выполняется код и какие переменные и объекты доступны.
У каждого контекста есть три важные части:
- Область видимости — показывает, какие переменные и функции доступны в данный момент.
- this — указывает на объект, к которому привязана текущая функция.
- Стек вызовов (call stack) — как стопка тарелок: JavaScript складывает туда функции, когда они вызываются, и убирает обратно, когда они завершаются.
Виды контекста в JS: глобальный, функциональный и this
1. Глобальный контекст. Когда страница загружается (или скрипт запускается), создаётся глобальный контекст. В браузере это объект window, в Node.js — global.Все переменные и функции, созданные вне других блоков, становятся частью этого объекта.
console.log(this); // В браузере: window
2. Контекст функции. Каждый раз, когда вызывается функция, создаётся новый контекст. Внутри него есть свои переменные, аргументы и значение this.
function greet() {
console.log(this); // В обычной функции this зависит от способа вызова
}
greet();
Если вызвать greet() просто так, this укажет на window (в нестрогом режиме).
3. Контекст объекта (this). Когда функция вызывается как метод объекта, this ссылается на этот объект.
const user = {
name: "Андрей",
greet() {
console.log(`Привет, ${this.name}`);
}
};
user.greet(); // Привет, Андрей
Здесь this ссылается на объект user, поэтому мы получаем имя пользователя.
Есть и другие контексты: у конструкторов, стрелочных функций и обработчиков событий. У каждого есть особенности, о которых мы расскажем в разделах справочника, посвящённых этим темам.
Стек вызовов: очерёдность выполнения кода
Когда JavaScript вызывает функцию, он кладёт её в стек вызовов — список, в котором отслеживается порядок выполнения. Это работает по принципу LIFO (last in, first out): последним пришёл, первым ушёл.
Рассмотрим на примере двух вложенных функций.
function first() {
second(); }
function second() {
console.log("Привет из второй функции!");
}
first();
Как меняется стек вызовов поэтапно:
- JavaScript начинает выполнение — стек пуст.
- Вызов first(). Функция first() добавляется в стек.
- Внутри first() вызывается second(). second() добавляется в стек поверх first().
- second() выполняет console.log. Вызов console.log() попадает в стек.
- console.log() завершился. После вывода в консоль, console.log() убирается из стека.
- second() завершилась, — она убирается из стека.
- first() завершилась, стек пуст.
Типичные ошибки при работе с функциями в JavaScript: как их избежать
Одна из распространённых ошибок при работе с функциями — забыть или неправильно использовать return.
return на новой строке без ()
function getNumber() {
return
42; // return завершает выполнение, и эта строка не выполнится!
}
console.log(getNumber()); // undefined
Почему так происходит: JavaScript думает, что return уже завершил функцию. А 42 он просто игнорирует.
Правильный вариант:
function getNumber() {
return 42; // Возвращаем число правильно
}
Если всё же хочется перенести число на новую строку, оберните его скобками:
function getNumber() {
return (
42
);
}
console.log(getNumber()); // 42
Нет return в некоторых ветках кода
function checkAge(age) {
if (age >= 18) {
return "Доступ разрешён";
}
// Здесь нет return!
}
console.log(checkAge(20)); // "Доступ разрешён"
console.log(checkAge(15)); // undefined (ожидали строку, но её нет)
Почему так: если age < 18, функция ничего не возвращает, и результат undefined.
Правильный вариант:
function checkAge(age) {
if (age >= 18) {
return "Доступ разрешён";
}
return "Доступ запрещён"; // Теперь всегда есть return
}
console.log(checkAge(15)); // «Доступ запрещён»
Рекурсивная функция без выхода
function countdown(n) {
console.log(n);
countdown(n - 1); // Функция вызывает саму себя без остановки!
}
countdown(5);
Что произойдёт:
- Функция countdown будет бесконечно уменьшать n.
- Когда n станет отрицательным, вызовы продолжатся.
- В итоге JavaScript выдаст «Maximum call stack size exceeded» (переполнение стека).
Чтобы всё исправить, надо добавить условие выхода.
Правильный вариант:
function countdown(n) {
if (n <= 0) { // Условие выхода
console.log("Стоп!");
return;
}
console.log(n);
countdown(n - 1);
}
countdown(5); // Выдаст 5 ... 4 ... 3 ... 2 ... 1 и остановится
null вместо undefined при значении по умолчанию
function greet(name = "Гость") {
console.log(`Привет, ${name}!`);
}
greet(null); // "Привет, null!"
Почему так: в функции задано значение по умолчанию ("Гость"), и мы хотим его использовать. Значения по умолчанию срабатывают, только если аргумент не определён (undefined). В JavaScript null и undefined часто используются как «отсутствие значения», но они не идентичны. Иногда разработчики явно задают null, думая, что это undefined.
Правильный вариант:
function greet(name = "Гость") {
console.log(`Привет, ${name}!`);
}
greet(); // "Привет, Гость!"
greet(undefined); // "Привет, Гость!"
Советы и лайфхаки для работы с функциями в JavaScript
Используйте понятные имена.
- Давайте функциям ясные и осмысленные названия, чтобы код было легче читать и понимать.
- Вместо неопределённого ct лучше использовать calculateTotal.
Пишите короткие и лаконичные функции.
- Одна функция должна выполнять одну конкретную задачу.
- Если код слишком разрастается, разбейте его на несколько функций.
Используйте const и let вместо var.
- const для неизменяемых переменных, let для изменяемых.
- Это улучшает читаемость и снижает вероятность ошибок.
Не изменяйте переданные аргументы.
- Функция не должна менять входные данные, если это не её основная цель.
- При необходимости возвращайте новый результат.
Используйте параметры по умолчанию.
- Позволяет избежать ошибок, если аргумент не передан.
Практика: тренируемся в использовании функций в JavaScript
Упражнение 1: сумма чисел, кратных 3
Напишите функцию, которая принимает массив целых чисел и возвращает сумму всех чисел, кратных 3.
Решение:
function sumMultipleOfThree(arr) {
let sum = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] % 3 === 0) {
sum += arr[i];
}
}
return sum;
}
Упражнение 2: проверка на палиндром
Напишите функцию, которая определяет, является ли переданная строка палиндромом. Палиндромом считается строка, которая читается одинаково как слева направо, так и справа налево.
Решение:
function isPalindrome(str) {
const reversedStr = str.split('').reverse().join('');
return str === reversedStr;
}
// Примеры использования:
console.log(isPalindrome('level')); ``// Вернёт true
console.log(isPalindrome('hello')); ``// Вернёт false
Здесь:
- str.split('') — превращает строку в массив символов (например, 'hello' → ['h', 'e', 'l', 'l', 'o'])
- reverse() — переворачивает массив ( ['h', 'e', 'l', 'l', 'o'] → ['o', 'l', 'l', 'e', 'h'])
- join('') — собирает массив обратно в строку ( ['o', 'l', 'l', 'e', 'h'] → 'olleh')
Сравниваем оригинал и перевёрнутую строку:
return str === reversedStr;
Упражнение 3. Генератор случайных сообщений
Напишите функцию, которая возвращает случайное сообщение из заранее заданного списка.
Список сообщений:
- «Ты молодец!»
- «Продолжай в том же духе!
- «Отличная работа!»
- «Ты на верном пути!»
Решение:
function generateRandomMessage() {
const messages = [
"Ты молодец!",
"Продолжай в том же духе!",
"Отличная работа!",
"Ты на верном пути!"
];
const index = Math.floor(Math.random() * messages.length); // Выбор случайного индекса из массива
return messages[index]; // Возврат выбранного сообщения
}
console.log(generateRandomMessage());
Здесь:
- Math.random() → генерирует случайное число от 0 до 1 (например, 0.72).
- Умножаем это число на messages.length (количество элементов в заданном списке, в данном случае 4).
- Math.floor(...) округляет вниз до целого числа от 0 до 3 — это и есть случайный индекс массива.
- return messages[index] — возвращается сообщение, определённое по индексу.
Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!