function expression
Baseline Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2015 года.
Ключевое слово function можно использовать для определения функции внутри выражения.
Вы также можете определять функции с помощью function объявления или стрелочного синтаксиса.
Попробуйте
const getRectArea = function (width, height) {
return width * height;
};
console.log(getRectArea(3, 4));
// Expected output: 12
Синтаксис
function (param0) {
statements
}
function (param0, param1) {
statements
}
function (param0, param1, /* …, */ paramN) {
statements
}
function name(param0) {
statements
}
function name(param0, param1) {
statements
}
function name(param0, param1, /* …, */ paramN) {
statements
}
Примечание: Выражение-инструкция не может начинаться с ключевого слова function, чтобы избежать неоднозначности с function объявлением. Ключевое слово function начинает выражение только тогда, когда оно появляется в контексте, который не может принимать инструкции.
Параметры
-
nameНеобязательный - Имя функции. Может быть опущено, в этом случае функция является анонимной. Имя локально только для тела функции.
-
paramNНеобязательный - Имя формального параметра функции. Синтаксис параметров см. в справке по функциям.
-
statementsНеобязательный - Инструкции, составляющие тело функции.
Описание
function выражение очень похоже и имеет почти такой же синтаксис, как и function объявление. Основное отличие между function выражением и function объявлением — это имя функции, которое может быть опущено в function выражениях для создания анонимных функций. function выражение может использоваться как IIFE (Immediately Invoked Function Expression — немедленно вызываемое функциональное выражение), которое выполняется сразу после определения. См. также главу о функциях для получения дополнительной информации.
Поднятие (hoisting) функциональных выражений
Функциональные выражения в JavaScript не поднимаются (hoisted), в отличие от объявлений функций. Вы не можете использовать функциональные выражения до того, как вы их создадите:
console.log(notHoisted); // undefined
// Even though the variable name is hoisted,
// the definition isn't. so it's undefined.
notHoisted(); // TypeError: notHoisted is not a function
var notHoisted = function () {
console.log("bar");
};
Именованное функциональное выражение
Если вы хотите обратиться к текущей функции внутри тела функции, вам нужно создать именованное функциональное выражение. Это имя затем локально только для тела функции (области видимости). Это позволяет избежать использования устаревшего arguments.callee свойства для рекурсивного вызова функции.
const math = {
factorial: function factorial(n) {
console.log(n);
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
},
};
math.factorial(3); // 3;2;1;
Если функциональное выражение имеет имя, свойство name функции будет установлено в это имя, вместо неявного имени, выведенного из синтаксиса (например, переменной, которой присвоена функция).
В отличие от объявлений, имя функциональных выражений доступно только для чтения.
"use strict";
function foo() {
foo = 1;
}
foo();
console.log(foo); // 1
(function foo() {
foo = 1; // TypeError: Assignment to constant variable.
})();
Примеры
Использование функционального выражения
Следующий пример определяет безымянную функцию и присваивает ее x. Функция возвращает квадрат своего аргумента:
const x = function (y) {
return y * y;
};
Использование функции в качестве обратного вызова
Чаще всего это используется как callback (функция обратного вызова):
button.addEventListener("click", function (event) {
console.log("button is clicked!");
});
Использование немедленно вызываемого функционального выражения (IIFE)
IIFE — это распространенный шаблон, используемый для выполнения произвольного количества инструкций в своей собственной области видимости (и, возможно, возврата значения) в месте, требующем одного выражения. Многие традиционные сценарии использования IIFE были заменены новыми синтаксическими возможностями, такими как модули и объявления с блочной областью видимости. Сами IIFE теперь чаще пишутся с использованием стрелочных функций, но суть остается той же. В общем случае IIFE выглядят так:
// standard IIFE
(function () {
// statements…
})();
// IIFE with arguments
(function (a, b) {
console.log(a + b);
})(1, 2); // logs 3
// IIFE being used to initialize a variable
const value = (() => {
const randomValue = Math.random();
if (randomValue > 0.5) {
return "heads";
}
return "tails";
})();
Здесь мы рассмотрим несколько вариантов использования с примерами.
Избегайте загрязнения глобального пространства имен в коде скриптов
Верхний уровень области видимости всех скриптов общий, что может включать множество функций и глобальных переменных из разных файлов. Поэтому, чтобы избежать конфликтов имен, важно ограничивать количество глобально объявленных имен (это значительно смягчается в модулях, но иногда ограничение области видимости временных переменных по-прежнему полезно, особенно когда файл очень длинный). Если у нас есть какой-то код инициализации, который нам больше не нужен, мы можем использовать шаблон IIFE, который лучше, чем использование объявления функции или функционального выражения, потому что он гарантирует, что код будет выполнен только здесь и один раз.
// top-level of a script (not a module)
var globalVariable = (() => {
// some initialization code
let firstVariable = something();
let secondVariable = somethingElse();
return firstVariable + secondVariable;
})();
// firstVariable and secondVariable cannot be accessed outside of the function body.
Паттерн модуля
Мы также будем использовать IIFE для создания приватных и публичных переменных и методов. Для более сложного использования паттерна модуля и других вариантов применения IIFE вы можете ознакомиться с книгой "Learning JavaScript Design Patterns" от Addy Osmani.
const makeWithdraw = (balance) =>
((copyBalance) => {
let balance = copyBalance; // This variable is private
const doBadThings = () => {
console.log("I will do bad things with your money");
};
doBadThings();
return {
withdraw(amount) {
if (balance >= amount) {
balance -= amount;
return balance;
}
return "Insufficient money";
},
};
})(balance);
const firstAccount = makeWithdraw(100); // "I will do bad things with your money"
console.log(firstAccount.balance); // undefined
console.log(firstAccount.withdraw(20)); // 80
console.log(firstAccount.withdraw(30)); // 50
console.log(firstAccount.doBadThings); // undefined; this method is private
const secondAccount = makeWithdraw(20); // "I will do bad things with your money"
console.log(secondAccount.withdraw(30)); // "Insufficient money"
console.log(secondAccount.withdraw(20)); // 0
Цикл for с var до ES6
Мы могли видеть следующее использование IIFE в старом коде, до появления let и const объявлений с блочной областью видимости. С инструкцией var у нас есть только функциональные области видимости и глобальная область видимости. Предположим, мы хотим создать 2 кнопки с текстом Button 0 и Button 1, и когда мы нажимаем на них, они должны выводить 0 и 1. Следующий код не работает:
for (var i = 0; i < 2; i++) {
const button = document.createElement("button");
button.innerText = `Button ${i}`;
button.onclick = function () {
console.log(i);
};
document.body.appendChild(button);
}
console.log(i); // 2
При нажатии обе кнопки Button 0 и Button 1 выводят 2, потому что i является глобальной, с последним значением 2. Чтобы решить эту проблему до ES6, мы могли использовать шаблон IIFE:
for (var i = 0; i < 2; i++) {
const button = document.createElement("button");
button.innerText = `Button ${i}`;
button.onclick = (function (copyOfI) {
return function () {
console.log(copyOfI);
};
})(i);
document.body.appendChild(button);
}
console.log(i); // 2
При нажатии кнопки Buttons 0 и 1 выводят 0 и 1. Переменная i определена глобально. Используя инструкцию let, мы можем просто сделать:
for (let i = 0; i < 2; i++) {
const button = document.createElement("button");
button.innerText = `Button ${i}`;
button.onclick = function () {
console.log(i);
};
document.body.appendChild(button);
}
console.log(i); // Uncaught ReferenceError: i is not defined.
При нажатии эти кнопки выводят 0 и 1.
Инструкции управления потоком в позициях выражений
IIFE позволяют нам использовать конструкции языка, такие как switch, в выражении.
someObject.property = (() => {
switch (someVariable) {
case 0:
return "zero";
case 1:
return "one";
default:
return "unknown";
}
})();
Этот подход может быть особенно полезен в сценариях, когда вы хотите сделать переменную const, но вынуждены использовать let или var во время инициализации:
let onlyAssignedOnce;
try {
onlyAssignedOnce = someFunctionThatMightThrow();
} catch (e) {
onlyAssignedOnce = null;
}
Используя IIFE, мы можем сделать переменную const:
const onlyAssignedOnce = (() => {
try {
return someFunctionThatMightThrow();
} catch (e) {
return null;
}
})();
Спецификации
Совместимость с браузерами
| Настольные компьютеры | Мобильные устройства | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
function |
1 |
12 |
1 |
3 |
1 |
18 |
4 |
10.1 |
1 |
1.0 |
4.4 |
1 |
1.0.0 |
1.0 |
0.10.0 |
trailing_comma |
58 |
14 |
52 |
45 |
10 |
58 |
52 |
43 |
10 |
7.0 |
58 |
10 |
1.0.0 |
1.0 |
8.0.0 |
См. также
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function