Skip to main content

Функции

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

Функции (Functions) - ключевая концепция в JavaScript. Важнейшей особенностью языка является поддержка функции первого класса (functions as first-class citizen). Любая функция это объект, и следовательно ею можно манипулировать как объектом, в частности:

  • Передавать как аргумент и возвращать в качестве результата при вызове других функций функций высшего порядка;
  • Создавать анонимно и присваивать в качестве значений переменных или свойств объектов.

Это определяет высокую выразительную мощность JavaScript и позволяет относить его к числу языков, реализующих функциональную парадигму программирования.

Объявление функции

Объявление функции (function definition, или function declaration, или function statement) состоит из ключевого слова function и следующих частей:

  • Имя функции (идентификатор), которое должно быть уникальным в рамках области видимости;
  • Список параметров в круглых скобках ();
  • Тело функции в фигурных скобках {}.

Синтаксис объявления функции:

function имяФункции(параметр1, параметр2, ..., параметрN) {
// тело функции
}

Пример объявления функции:

function showMessage(message) {
console.log(message);
}

Функции как выражения

Функции могут быть объявлены как выражения (function expression). В этом случае функция не имеет имени (анонимная функция) и присваивается переменной.

const showMessage = function (message) {
console.log(message);
};

showMessage("Hello, World!");

Или функция может быть объявлена как стрелочная функция (arrow function).

const showMessage = (message) => {
console.log(message);
};

showMessage("Hello, World!");

Вызов функции

Вызов функции (function call, или function invocation) - это процесс выполнения кода функции. Для вызова функции используется имя функции, за которым следуют круглые скобки (). Если функция принимает параметры, то их значения передаются в круглых скобках.

function sayHello() {
console.log("Hello, World!");
}

function showMessage(message) {
console.log(message);
}

sayHello(); // вызов функции без параметров

showMessage("Hello, World!"); // вызов функции с параметром

Параметры функции

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

function showMessage(message) {
console.log(message);
}

Параметры по умолчанию

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

function showMessage(message = "Hello, World!") {
console.log(message);
}

showMessage(); // Hello, World!
showMessage("Hello, JavaScript!"); // Hello, JavaScript!

Важно помнить, что параметры со значением по умолчанию должны идти после параметров без значения по умолчанию.

function showMessage(message, count = 1) {
for (let i = 0; i < count; i += 1) {
console.log(message);
}
}

showMessage("Hello, World!"); // Hello, World!

showMessage("Hello, JavaScript!", 3); // Hello, JavaScript!

Если параметр по умолчанию идет перед параметром без значения по умолчанию, то это вызовет ошибку.

function showMessage(count = 1, message) {
// SyntaxError: Unexpected token '='
for (let i = 0; i < count; i += 1) {
console.log(message);
}
}

Оператор расширения (rest operator)

Оператор расширения (rest operator) позволяет передавать переменное количество аргументов в функцию. Оператор расширения представляется тремя точками ... перед именем параметра. При этом все аргументы, переданные в функцию, собираются в массив.

function sum(...args) {
let total = 0;

for (const arg of args) {
total += arg;
}

return total;
}

сonsole.log(sum(1, 2, 3)); // 6
сonsole.log(sum(1, 2, 3, 4, 5)); // 15

Оператор расширения (spread operator)

Оператор расширения (spread operator) позволяет передавать элементы массива в качестве аргументов функции. Оператор расширения представляется тремя точками ... перед именем массива. При этом каждый элемент массива передается в функцию как отдельный аргумент.

function sum(a, b, c) {
return a + b + c;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers)); // 6

Важно помнить, что оператор расширения должен быть последним в списке параметров функции.

function sum(a, b, ...args) {
let total = a + b;

for (const arg of args) {
total += arg;
}

return total;
}

В противном случае это вызовет ошибку.

function sum(...args, a, b) { // SyntaxError: Rest parameter must be last formal parameter
let total = 0;

for (const arg of args) {
total += arg;
}

return total + a + b;
}

Деструктуризация параметров

Деструктуризация параметров (destructuring parameters) позволяет извлекать значения из объектов и массивов и использовать их как параметры функции.

function showUser({ name, age }) {
console.log(`Name: ${name}, Age: ${age}`);
}

const user = {
name: "Alice",
age: 25,
};

showUser(user); // Name: Alice, Age: 25

Ключевое слово return

Возвращаемое значение (return value) - это значение, которое возвращает функция после выполнения своего кода. Возвращаемое значение функции определяется ключевым словом return, за которым следует значение, которое функция возвращает.

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

const total = sum(2, 3);

console.log(total); // 5

Если функция не возвращает значение, то она возвращает undefined.

function showMessage(message) {
console.log(message);
}

const result = showMessage("Hello, World!");

console.log(result); // undefined

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

function sum(a, b) {
return a + b;

console.log("This code will not be executed"); // Этот код не будет выполнен
}

const total = sum(2, 3);

console.log(total); // 5

Деструктуризация возвращаемого значения

Деструктуризация возвращаемого значения (destructuring return value) позволяет извлекать значения из объектов и массивов, возвращаемых функцией.

Деструктуризация объекта:

function getPerson() {
return {
name: "Alice",
age: 25,
};
}

const { name, age } = getPerson();

console.log(name); // Alice

console.log(age); // 25

Деструктуризация массива:

function getPerson() {
return ["Alice", 25];
}

const [name, age] = getPerson();

console.log(name); // Alice

console.log(age); // 25

Область видимости функции

Область видимости (scope) функции определяет доступность переменных и функций внутри функции.

Переменные объявленные в функции не могут быть доступными где-нибудь вне этой функции, поэтому переменные (которые нужны именно для функции) объявляют только в scope функции. При этом функция имеет доступ ко всем переменным и функциям, объявленным внутри её scope. Другими словами функция объявленная в глобальном scope имеет доступ ко всем переменным в глобальном scope. Функция объявленная внутри другой функции ещё имеет доступ и ко всем переменным её родительской функции и другим переменным, к которым эта родительская функция имеет доступ.

// Следующие переменные объявленны в глобальном scope
let num1 = 20;
let num2 = 3;
let firstName = "Chamahk";

// Эта функция объявленна в глобальном scope
function multiply() {
return num1 * num2;
}

multiply(); // вернёт 60

// Пример вложенной функции
function getScore() {
let num1 = 2;
let num2 = 3;

function add() {
return firstName + " scored " + (num1 + num2);
}

return add();
}

console.log(getScore());
console.log(multiply());

Замыкание

Замыкание (closure) - это функция, которая запоминает окружение, в котором она была создана. Замыкание позволяет функции использовать переменные, объявленные вне ее, даже после того, как эта функция завершила свою работу.

function createCounter() {
let count = 0;

return function () {
count += 1;
return count;
};
}

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Ключевое слово this в функции

Ключевое слово this в JavaScript ссылается на объект, в контексте которого вызывается функция. Значение this зависит от того, как вызывается функция.

function showMessage() {
console.log(this);
}

showMessage(); // Window
const user = {
name: "Alice",
show() {
console.log(this);
},
};

user.show(); // { name: 'Alice', show: [Function: show] }

Анонимные функции

Анонимная функция (anonymous function) - это функция, которая не имеет имени. Анонимные функции используются в качестве аргументов других функций, возвращаемых значений функций, а также для создания замыканий.

const showMessage = function (message) {
console.log(message);
};

showMessage("Hello, World!");
const numbers = [1, 2, 3, 4, 5];

const evenNumbers = numbers.filter(function (number) {
return number % 2 === 0;
});
function createCounter() {
let count = 0;

return function () {
count += 1;
return count;
};
}

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Стрелочные функции

Cтрелочные функции (arrow functions) - это сокращенный синтаксис для объявления функций. Стрелочные функции не имеют собственного контекста (this), поэтому они не могут быть использованы как конструкторы и не имеют прототипа.

const showMessage = (message) => {
console.log(message);
};
const numbers = [1, 2, 3, 4, 5];

const evenNumbers = numbers.filter((number) => number % 2 === 0);

console.log(evenNumbers); // [2, 4]
const createCounter = () => {
let count = 0;

return () => {
count += 1;
return count;
};
};

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Разница между function и arrow function

Главное отличие между function и arrow function заключается в том, что стрелочные функции не имеют собственного контекста (this). В стрелочных функциях this ссылается на контекст окружающей функции.

function showMessage() {
console.log(this);
}

showMessage(); // Window
const showMessage = () => {
console.log(this);
};

showMessage(); // Window
const user = {
name: "Alice",
showName: function () {
console.log(this.name);
},
};

user.showName(); // Alice
const user = {
name: "Alice",
showName: () => {
console.log(this.name);
},
};

user.showName(); // undefined

Функции высшего порядка

Вы можете вложить одну функцию в другую. Вложенная функция (nested function; inner) приватная (private) и она помещена в другую функцию (outer). Так образуется замыкание (closure). Closure — это выражение (обычно функция), которое может иметь свободные переменные вместе со средой, которая связывает эти переменные (что "закрывает" ("close") выражение).

Поскольку вложенная функция это closure, это означает, что вложенная функция может "унаследовать" (inherit) аргументы и переменные функции, в которую та вложена. Другими словами, вложенная функция содержит scope внешней ("outer") функции.

function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
сonsole.log(addSquares(2, 3)); // 13
сonsole.log(addSquares(3, 4)); // 25
сonsole.log(addSquares(4, 5)); // 41

Рекурсия

Рекурсия (recursion) - это процесс, при котором функция вызывает саму себя. Рекурсия позволяет решать задачи, которые могут быть разбиты на более мелкие подзадачи того же типа. Рекурсивные функции могут быть более читаемыми и понятными, чем итеративные функции.

function factorial(n) {
if (n === 0) {
return 1;
}

return n * factorial(n - 1);
}

console.log(factorial(5)); // 120

некоторые алгоритмы не могут быть простыми повторяющимися циклами. Например, получение всех элементов структуры дерева проще всего реализуется использованием рекурсии.

Чистые функции

Чистая функция (pure function) - это функция, которая возвращает результат, зависящий только от своих аргументов, и не имеет побочных эффектов. Чистые функции не изменяют состояние программы и не взаимодействуют с внешними данными.


// Чистая функция

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

console.log(sum(2, 3)); // 5

// Нечистая функция

let total = 0;

function sum(a) {
total += a;
return total;
}

console.log(sum(2)); // 2

console.log(sum(3)); // 5

Побочные эффекты

Побочный эффект (side effect) - это изменение состояния программы, которое происходит в результате выполнения функции. Побочные эффекты могут быть изменением переменных, выводом на экран, взаимодействием с внешними данными и т.д.

let total = 0;

function sum(a) {
total += a;
return total;
}

console.log(sum(2)); // 2

console.log(sum(3)); // 5

Предикаты

Предикат (predicate) - это функция, которая возвращает логическое значение (true или false). Предикаты используются для проверки условий и фильтрации данных.

function isEven(number) {
return number % 2 === 0;
}

console.log(isEven(2)); // true

console.log(isEven(3)); // false

Соглашения об именовании (Naming conventions)

  • При именовании функций следует использовать camelCase.
  • Имя функции должно быть глаголом или фразой, описывающей действие, которое она выполняет. Имя функции должно быть понятным и описательным, чтобы другие разработчики могли понять, что делает функция, не читая ее код.
  • Если функция является предикатом (функция, возвращающая логическое значение), то имя функции должно начинаться с is, has, can, should и т.д. Например, isAdult, hasPermission, canEdit, shouldRender.
  • Если функция возвращает значение, то имя функции должно быть существительным или фразой, описывающей возвращаемое значение. Например, getUserName, getTotalPrice, getErrorMessage.
  • Если функция изменяет состояние, то имя функции должно начинаться с set, update, delete, remove и т.д. Например, setUserName, updateTotalPrice, deleteUser, removeItem.
  • Если функция выполняет действие, то имя функции должно быть глаголом или фразой, описывающей действие. Например, showMessage, openModal, closeMenu, logError.