--- title: Функции slug: Web/JavaScript/Reference/Functions tags: - Функции - Функция translation_of: Web/JavaScript/Reference/Functions --- <div>{{jsSidebar("Functions")}}</div> <h2 id="Summary" name="Summary">Сводка</h2> <p>В общем случае, функция — это "подпрограмма", которую можно <em>вызывать</em> из внешнего (или внутреннего, в случае рекурсии) по отношению к функции кода. Как и сама программа, функция состоит из последовательности инструкций, называемой <em>телом функции.</em> Значения могут быть <em>переданы</em> в функцию, а функция <em>вернёт</em> значение.</p> <p>В JavaScript функции являются объектами первого класса, то есть: они являются объектами и с ними можно взаимодействовать и передавать их точно так же как любой другой объект. Если быть точным, функции — это объекты <code><a href="ru/docs/Web/JavaScript/Reference/Global_Objects/Function">Function</a></code>.</p> <p>Больше подробностей и примеров можно найти в <a href="/ru/docs/Web/JavaScript/Guide/Functions">руководстве по функциям в JavaScript</a>.</p> <h2 id="Описание">Описание</h2> <p>Каждая функция в JavaScript — это объект Function. О свойствах и методах объектов Function можно прочитать в статье {{jsxref("Function")}}.</p> <p>Функции — это не процедуры. Функция всегда возвращает значение, а процедура может возвращать, а может не возвращать.</p> <p>Чтобы вернуть значение, отличное от значения по умолчанию, в функции должна быть инструкция <code><a href="/ru/docs/Web/JavaScript/Reference/Statements/return">return</a></code>, которая указывает, что именно нужно вернуть. Функция без него вернёт значение по умолчанию. В случае <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">конструктора</a>, вызванного с ключевым словом <code><a href="/ru/docs/Web/JavaScript/Reference/Operators/new">new</a>, </code>значение по умолчанию — это значение его параметра <code>this</code>. Для остальных функций значением по умолчанию будет <code>undefined</code>.</p> <p>Параметры вызова функции называются <em>аргументами</em> функции. Аргументы передаются в функцию <em>по значению</em>. Если функция изменяет значение аргумента, это изменение не отражается на глобальном состоянии или вызывающей функции. Однако ссылки на объекты — это тоже значения, и они отличаются тем, что если функция изменяет свойства объекта по ссылке, это изменение видно снаружи функции, как показано в примере ниже.</p> <pre class="brush: js">/* Объявляем функцию 'myFunc' */ function myFunc(theObject) { theObject.brand = "Toyota"; } /* * Объявляем переменную 'mycar'; * создаём и инициализируем новый Object; * приравниваем 'mycar' к ссылке на него */ var mycar = { brand: "Honda", model: "Accord", year: 1998 }; /* Выведет 'Honda' */ console.log(mycar.brand); /* Передаём ссылку на объект в функцию */ myFunc(mycar); /* * Выведет 'Toyota', так как значение свойства 'brand' * было изменено внутри функции. */ console.log(mycar.brand); </pre> <p><a href="/ru/docs/Web/JavaScript/Reference/Operators/this"><code>Ключевое слово this</code></a> не ссылается на функцию, которая выполняется в данный момент, поэтому вы должны обращаться к объектами Function по имени, даже внутри тела самой функции.</p> <h2 id="Defining_functions" name="Defining_functions">Определение функций</h2> <p>Есть несколько способов определить функцию:</p> <h3 id="The_function_declaration_.28function_statement.29" name="The_function_declaration_.28function_statement.29">Объявление функции (инструкция <code>function</code>)</h3> <p>Специальный синтаксис для объявления функций (более подробно: <a href="/ru/docs/Web/JavaScript/Reference/Statements/function">function statement</a>):</p> <pre>function <em>name</em>([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) { <em>statements</em> } </pre> <dl> <dt><code>name</code></dt> <dd>Имя функции.</dd> </dl> <dl> <dt><code>param</code></dt> <dd>Имя аргумента, передаваемого в функцию. У функции может быть не более 255 аргументов.</dd> </dl> <dl> <dt><code>statements</code></dt> <dd>Инструкции, из которых состоит тело функции.</dd> </dl> <h3 id="The_function_expression_.28function_operator.29" name="The_function_expression_.28function_operator.29">Функция-выражение (оператор <code>function</code>)</h3> <p>Функция-выражение похожа на определение функции и имеет такой же синтаксис (более подробно: <a href="/ru/docs/Web/JavaScript/Reference/Operators/function">function operator</a>):</p> <pre>function [<em>name</em>]([<em>param</em>] [, <em>param</em>] [..., <em>param</em>]) { <em>statements</em> } </pre> <dl> <dt><code>name</code></dt> <dd>Имя функции. Может быть не указано, в таком случае функция становится анонимной.</dd> </dl> <dl> <dt><code>param</code></dt> <dd>Имя аргумента, передаваемого в функцию. У функции может быть не более 255 аргументов.</dd> <dt><code>statements</code></dt> <dd>Инструкции, из которых состоит тело функции.</dd> </dl> <h3 id="Стрелочная_функция-выражение_(>)">Стрелочная функция-выражение (=>)</h3> <div class="note"> <p><strong>Заметка:</strong> стрелочные функции являются экспериментальной технологией<em>,</em> частью спецификации ECMAScript 6 и пока что не поддерживаются всеми браузерами.</p> </div> <p>Стрелочные функции отличаются более кратким синтаксисом и тем, что они лексически связывают значение своего <code>this (подробнее об этом в статье <a href="/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Стрелочные функции</a>):</code></p> <pre>([param] [, param]) => { statements } param => expression </pre> <dl> <dt><code>param</code></dt> <dd>Имя параметра. Если параметров нет, вместо них нужно поставить (). Если параметров больше одного, их также нужно заключить в ().</dd> <dt><code>statements or expression</code></dt> <dd>Если инструкций несколько, их нужно заключить в {}. Для одного выражения фигурных скобок не требуется, а результат этого выражения будет возвращён функцией (то есть<code> функция x => 3 + 8 вернёт 11).</code><code> </code></dd> </dl> <h3 id="The_Function_constructor" name="The_Function_constructor">Конструктор <code>Function</code></h3> <div class="note"> <p><strong>Заметка:</strong> Использовать конструктор Function не рекомендуется, так как он принимает тело функции в виде строки, а это может помешать оптимизациям, которые выполняют движки JavaScript, а также привести к другим проблемам.</p> </div> <p>Объекты {{jsxref("Function")}} можно создавать с помощью оператора <code>new </code>(как и любые другие объекты):</p> <pre>new Function (<em>arg1</em>, <em>arg2</em>, ... <em>argN</em>, <em>functionBody</em>) </pre> <dl> <dt><code>arg1, arg2, ... arg<em>N</em></code></dt> <dd>Ноль или больше имён параметров функции. Имя должно быть строкой, содержащей валидный идентификатор JavaScript. Если параметров несколько, они должны быть разделены запятыми. Например: "<code>x</code>", "<code>theValue</code>", или "<code>a,b</code>".</dd> </dl> <dl> <dt><code>functionBody</code></dt> <dd>Инструкции, из которых состоит тело функции.</dd> </dl> <p>Конструктор <code>Function</code> можно вызывать и без оператора <code>new,</code> эффект будет тем же.</p> <h2 id="Параметры_функции">Параметры функции</h2> <div class="note"> <p><strong>Примечание:</strong> Оставшиеся параметры и параметры по умолчанию <em>— это экспериментальная </em>технология, часть спецификации ECMAScript 6, и они пока ещё не получили широкой поддержки среди браузеров.</p> </div> <h3 id="Параметры_по_умолчанию">Параметры по умолчанию</h3> <p>Параметры функции по умолчанию позволяют инициализировать формальные параметры со значениями по умолчанию, если им не было передано значение, или было передано <code>undefined</code>. Подробнее о них можно узнать в статье <a href="/ru/docs/Web/JavaScript/Reference/Functions/Default_parameters">Параметры по умолчанию</a>.</p> <h3 id="Оставшиеся_параметры">Оставшиеся параметры</h3> <p>Синтаксис оставшихся параметров позволяет передать бесконечное число аргументов как массив. Подробности можно найти в статье <a href="/ru/docs/Web/JavaScript/Reference/Functions/rest_parameters">Оставшиеся параметры</a>.</p> <h2 id="The_arguments_object" name="The_arguments_object">Объект <code>arguments</code></h2> <p>Внутри функции получить доступ к её аргументам можно через объект <a href="/ru/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>.</p> <ul> <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments">arguments</a></code>: Объект, похожий на массив и содержащий все аргументы, переданные в текущую функцию.</li> <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee">arguments.callee</a></code> {{Deprecated_inline}}: Функция, исполняемая в текущий момент.</li> <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/caller">arguments.caller</a></code> {{Obsolete_inline}} : Функция, которая вызвала текущую функцию.</li> <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/length">arguments.length</a></code>: Число аргументов, переданных в функцию.</li> </ul> <h2 id="Определение_методов">Определение методов</h2> <h3 id="Геттеры_и_сеттеры">Геттеры и сеттеры</h3> <p>Можно определять геттеры (методы для чтения) и сеттеры (методы для изменения) для любого встроенного или пользовательского объекта, который поддерживает добавление новых свойств. Для этого используется синтаксис литерала объекта.</p> <dl> <dt><a href="/en-US/docs/Web/JavaScript/Reference/Functions/get">get</a></dt> <dd>Связывает свойство объекта с функцией, которая будет вызвана при обращении к свойству.</dd> <dt><a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">set</a></dt> <dd>Связывает свойство объекта с функцией, которая будет вызвана при попытке изменения свойства.</dd> </dl> <h3 id="Синтаксис_определения_методов">Синтаксис определения методов</h3> <div class="note"> <p><strong>Примечание:</strong> <em>Определение методов — это экспериментальная </em>технология, часть спецификации ECMAScript 6, и она пока ещё не получила широкой поддержки среди браузеров.</p> </div> <p>Начиная с ECMAScript 6, можно определять собственные методы, используют более краткий синтаксис, похожий на геттеры и сеттеры. Более подробно — в статье <a href="/ru/docs/Web/JavaScript/Reference/Functions/Method_definitions">Определение методов.</a></p> <pre class="brush: js">var obj = { foo() {}, bar() {} };</pre> <h2 id="Function_constructor_vs._function_declaration_vs._function_expression" name="Function_constructor_vs._function_declaration_vs._function_expression">Сравнение конструкторов <code>Function</code> с объявлением функций и функциями-выражениями</h2> <p>Посмотрите на следующие примеры:</p> <p>Функция, определённая через конструктор <code>Function</code> и приравненная к переменной <code>multiply:</code></p> <pre class="brush: js">var multiply = new Function("x", "y", "return x * y");</pre> <p>Объявление функции multiply:</p> <pre class="brush: js">function multiply(x, y) { return x * y; } </pre> <p>Анонимная функция-выражение, приравненная к переменной<code> multiply:</code></p> <pre class="brush: js">var multiply = function(x, y) { return x * y; }; </pre> <p><em>Функция-выражение</em> с именем <code>func_name</code>, приравненное к переменной<code> multiply:</code></p> <pre class="brush: js">var multiply = function func_name(x, y) { return x * y; }; </pre> <h3 id="Отличия">Отличия</h3> <p>Во всех случаях результат примерно одинаков, но есть несколько нюансов:</p> <p>Имя функции и переменная, к которой функция приравнена — это не одно и то же. Имя функции нельзя менять, а вот переменной, к которой приравнена функция, можно дать другое значение. В случае функции-выражения с именем, это имя может быть использовано только внутри самой функции. При попытке использовать его снаружи возникнет ошибка (а если ранее была объявлена переменная с таким именем, будет возвращено <code>undefined</code>). Например:</p> <pre class="brush: js">var y = function x() {}; alert(x); // выкинет ошибку </pre> <p>Также имя функции-выражения проявляется, если сериализовать функцию через метод <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/toString">Function.toString.</a></p> <p>А вот переменная, к которой функция приравнена, ограничена только собственной областью видимости, которая включает ту область, где функция была объявлена.</p> <p>Как показано в четвёртом примере, имя функции может отличаться от имени переменной, к которой функция приравнена, эти имена никак не связаны. Объявление функции (function declaration) также создаёт и переменную с именем, аналогичным имени функции. Таким образом:</p> <ol> <li>Если функция определена с помощью функции-выражения (function expression), её имя доступно только внутри самой функции.</li> <li>Если функция объявлена (function declaration), её имя доступно в той области видимости, где функция была определена.</li> </ol> <p>У функции, определённой с помощью '<code>new Function'</code>, нет имени. Однако, в JavaScript движке <a href="/en-US/docs/Mozilla/Projects/SpiderMonkey">SpiderMonkey</a>, сериализованное представление функции отображается так, как будто оно имеет имя "anonymous". Например, , <code>alert(new Function())</code> выдаст:</p> <pre class="brush: js">function anonymous() { } </pre> <p>Так как на самом деле у функции нет имени, переменную <code>anonymous</code> нельзя использовать внутри функции. Например, следующий пример выкинет ошибку:</p> <pre class="brush: js">var foo = new Function("alert(anonymous);"); foo(); </pre> <p>В отличии от функций, определённых через функцию-выражение или конструктор <code>Function</code>, функция, определённая через объявление, может быть использована перед тем, как была определена. Например:</p> <pre class="brush: js">foo(); // выведет FOO! function foo() { alert('FOO!'); } </pre> <p>Функция, определённая через функцию-выражение, наследует текущую область видимости, то есть создаёт замыкание. А вот функция, созданная с помощью конструктора <code>Function</code>, не наследует ничего, кроме глобальной области видимости (её наследуют вообще все функции).</p> <p>Функции, определённые через функцию-выражение и объявление функции парсятся только один раз, в отличии от функций, созданных с помощью конструктора. То есть строка, которая передаётся в конструктор <code>Function</code>, парсится при каждом вызове конструктора. И хотя функция-выражение каждый раз создаёт замыкание, тело функции при этом не парсится, и получается, что функции-выражение всё равно быстрее, чем "<code>new Function(...)</code>". Поэтому конструктора <code>Function</code> в большинстве случаев стоит избегать, если это возможно.</p> <p>Стоит отметить, что функции-выражения и объявления функций внутри функции, созданной при парсинге конструктора <code>Function</code>, парсятся только один раз. Например:</p> <pre class="brush: js">var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))(); foo(); // "function() {\n\talert(bar);\n}" Эта часть строки, составляющей тело функции, не парсится во второй раз.</pre> <p>Объявление функции можно очень легко (и часто случайно) превратить в функцию-выражение. Объявление функции перестаёт быть таковым, если оно:</p> <ul> <li>становится частью выражения</li> <li>не является "исходным элементом" функции или файла. Исходный элемент - это не вложенный элемент внутри функции или скрипта:</li> </ul> <pre class="brush: js">var x = 0; // исходный элемент if (x == 0) { // исходный элемент x = 10; // не исходный элемент function boo() {} // не исходный элемент } function foo() { // исходный элемент var y = 20; // исходный элемент function bar() {} // исходный элемент while (y == 10) { // исходный элемент function blah() {} // не исходный элемент y++; // не исходный элемент } } </pre> <h3 id="Примеры">Примеры</h3> <pre class="brush: js">// объявление функции function foo() {} // функция-выражение (function bar() {}) // функция-выражение x = function hello() {} if (x) { // функция-выражение function world() {} } // объявление функции function a() { // обявление функции function b() {} if (0) { // функция-выражение function c() {} } } </pre> <h2 id="Conditionally_defining_a_function" name="Conditionally_defining_a_function">Определение функции в зависимости от условия</h2> <p>Функции могут быть определены в зависимости от условий с помощью инструкции <code>function (разрешённое расширение стандарта</code> <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262 Edition 3</a>) или конструктора <code>Function</code>. Обратите внимание, что подобные инструкции <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=609832">запрещены в ES5 strict</a>. Кроме того, эта возможность по-разному ведёт себя в разных браузерах, поэтому не стоит на неё рассчитывать.</p> <p>В коде ниже функция <code>zero</code> никогда не будет определена и не может быть вызвана, потому что '<code>if (0)</code>' всегда расценивается как <code>false</code>:</p> <pre class="brush: js">if (0) { function zero() { document.writeln("This is zero."); } } </pre> <p>Если изменить условие на '<code>if (1)</code>', функция <code>zero</code> будет определена.</p> <p>Заметьте, что хотя это выглядит как объявление функции, на самом деле, это функция-выражение (или инструкция), так как она вложена внутрь другой инструкции. Изучите разницу между объявлением функции и функцией-выражением.</p> <p>Некоторые JavaScript-движки (но не <a href="/en-US/docs/SpiderMonkey">SpiderMonkey</a>), неверно считают любую функцию-выражение с именем за объявление функции. Это приводит к тому, что функция <code>zero</code> будет определена, даже если условие всегда <code>false</code>. Более безопасный способ определить функцию по условию - это сделать её анонимной и приравнять к переменной:</p> <pre class="brush: js">if (0) { var zero = function() { document.writeln("This is zero."); } } </pre> <h2 id="Examples" name="Examples">Примеры</h2> <h3 id="Example:_Returning_a_formatted_number" name="Example:_Returning_a_formatted_number">Пример: возврат отформатированного числа</h3> <p>Эта функция возвращает строку, содержащую число с заданным количеством нулей перед ним:</p> <pre class="brush: js">function padZeros(num, totalLen) { var numStr = num.toString(); // Инициализировать возвращаемое значение в виде строки var numZeros = totalLen - numStr.length; // Посчитать число нулей в начале for (var i = 1; i <= numZeros; i++) { numStr = "0" + numStr; } return numStr; } </pre> <p>Вызовем <code>padZeros</code>:</p> <pre class="brush: js">var result; result = padZeros(42,4); // возвращает "0042" result = padZeros(42,2); // возвращает "42" result = padZeros(5,4); // возвращает "0005" </pre> <h3 id="Example:_Determining_whether_a_function_exists" name="Example:_Determining_whether_a_function_exists">Пример: существует ли функция</h3> <p>Можно определить, существует ли функция с помощью оператора <code>typeof</code>. В следующем примере проверяется, есть ли у объекта <code>window</code> функция <code>noFunc</code>. Если есть, то она вызывается; если нет, выполняется какое-то другое действие.</p> <pre class="brush: js"> if ('function' == typeof window.noFunc) { // вызывать noFunc() } else { // сделать что-то другое } </pre> <p>Заметьте, что в проверке условия используется ссылка на <code>noFunc</code> — после имени функции нет скобок, поэтому сама функция не вызывается.</p> <h2 id="Спецификации">Спецификации</h2> <table class="standard-table"> <tbody> <tr> <th scope="col">Спецификация</th> <th scope="col">Статус</th> <th scope="col">Комментарий</th> </tr> <tr> <td>ECMAScript 1st Edition.</td> <td>Стандарт</td> <td>Изначальное определение. Релизовано в JavaScript 1.0</td> </tr> <tr> <td>{{SpecName('ES5.1', '#sec-13', 'Function Definition')}}</td> <td>{{Spec2('ES5.1')}}</td> <td> </td> </tr> <tr> <td>{{SpecName('ES6', '#sec-function-definitions', 'Function definitions')}}</td> <td>{{Spec2('ES6')}}</td> <td>Новое: стрелочные функции, генераторы, параметры по умолчанию, оставшиеся параметры</td> </tr> </tbody> </table> <h2 id="Поддержка_браузерами">Поддержка браузерами</h2> <p>{{ CompatibilityTable() }}</p> <div id="compat-desktop"> <table class="compat-table"> <tbody> <tr> <th>Feature</th> <th>Chrome</th> <th>Firefox (Gecko)</th> <th>Internet Explorer</th> <th>Opera</th> <th>Safari</th> </tr> <tr> <td>Начальная поддержка</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> </tr> </tbody> </table> </div> <div id="compat-mobile"> <table class="compat-table"> <tbody> <tr> <th>Feature</th> <th>Android</th> <th>Chrome for Android</th> <th>Firefox Mobile (Gecko)</th> <th>IE Mobile</th> <th>Opera Mobile</th> <th>Safari Mobile</th> </tr> <tr> <td>Начальная поддержка</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> <td>{{ CompatVersionUnknown() }}</td> </tr> </tbody> </table> </div> <h2 id="See_also" name="See_also">См. также</h2> <ul> <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function"><code>Function</code></a></li> <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/function">Инструкция<code> function</code></a></li> <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/function">Оператор<code> function</code></a></li> </ul>