Jscript функции. JavaScript: Функции. Аргументы и параметры функций

Идеи динамичного формирования контента на web-ресуре стали нормой. Статические страницы и шаблонное сайтостроение окончательно завершили свою миссию.

Однако современный web-ресурс не обязательно должен быть представлен набором страниц, формируемых сервером и обновляемых браузером (JS+AJAX).

Web-ресурс в момент прихода посетителя может представлять собой пару заголовков для протокола, немного текста в «head», несколько строк кода в «body» и все. Остальное «додумается » в процессе работы посетителя - это идеальный сайт или стремящийся быть таковым.

Место описания и сущность функций

JavaScript - это опыт, наработаный многими десятилетиями. Он имеет значимую историю развития, современную квалифицированную команду создателей-разработчиков. Язык отлично продуман, надежен, красив и дает настоящую возможность разработчикам писать приличный код и самосовершенствоваться.

Понятие алгоритма вне функции здесь отсутствует в принципе. Разумеется, разработчик может в любом месте страницы вставить скрипт, поместить в него код и он будет исполнен. Но какой смысл в коде, который исполняется только раз: при загрузке (перегрузке) страницы? Разве что можно установить начальные значения каких-нибудь малозначимых переменных.

Скрипт - это место описания нужных переменных и функций, нежели добрый кусок кода, написанный ради самого себя. Именно набор функций является существенным и значимым, возможно - их взаимная непосредственная связь, но чаще бывает все иначе. Место описания функции и место ее применения вовсе не одно и тоже.

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

Функциональная динамика

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

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

Изначально здесь нет никакой последовательности и нет никакой параллельности. Здесь есть адекватная реакция web-ресурса на события. Насколько быстро JavaScript отработает ту или иную функцию, зависит от многих технических (компьютер, линии связи) и семантических (логика алгоритма, предметная область, смысл задачи) факторов.

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

Это новое мышление в разработке: распределенная обработка информации в недрах отдельно взятого браузера!

Синтаксис переменных и функций

JavaScript-переменные размещаются как в теге «script», так и в теле функции. Функции определяются так же. Особого смысла писать внутри функции еще одну функцию нет, но это может быть необходимо по различным и вполне обоснованным причинам.

Описание функции в общем случае начинается с ключевого слова «function», за которым следует ее имя, список аргументов в круглых скобках через запятую и тело функции в фигурных скобках.

В данном примере описаны две функции, обеспечивающие AJAX-обмен между страницей и сервером. Переменная scXHR описана выше, потому доступна как в InitXML, так и внутри WaitReplySC.

Имя функции и парамет «функция»

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

Здесь важно также отметить, что WaitReplySC - это функция. Но в строке scXHR.onreadystatechange = WaitReplySC она передается как параметр. Это общее правило передачи функций в другие функции в качестве параметров. Указал скобки и передал в них ее параметр (параметры) - функция исполнится немедленно. Передал только имя, ну и что с того. Вызов функции сделает тот, кто получил ее имя.

Функциональность, реализуемая через AJAX, позволяет выполнить вызов функции JavaScript через данные, полученные от сервера. Фактически, посылая запрос на сервер, та или иная функция может вовсе и не «знать», к какой функции она обращается и с какой информацией.

Выход из функции и ее результат

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

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

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

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

Аргументы функций

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

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

Изменение аргумента функции действительно внутри функции, но не вне ее. Для того чтобы что-то изменить вне функции, нужно воспользоваться оператором JavaScript return, через который передать необходимое значение наружу.

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

У arguments есть свойство callee, которое предназначено для вызова функции, что выполняется в данный момент времени. Если вызвать саму себя, то вариант JavaScript функция в функции позволит реализовать рекурсию.

Использование функций

Основная забота функций - обслуживать события браузера. Для этого практически в каждом теге есть возможность указать имя события и функцию, его обрабатывающую. Можно указывать несколько событий, но на каждое событие указывается только одна функция.

Одна функция может обслуживать несколько элементов страницы и несколько событий. Посредством параметра «this» можно передать функции информацию, откуда она была вызвана.

Классическое использование JS-функций - обработчики событий на элементах. В данном примере в форме входа/выхода посетителя будет вызвана функция scfWecomeGo() или scfWelcomeCancel(), а при выборе режима работы scfMenuItemClick(this).

В последнем случае передается параметр «this», который позволяет чудесным образом узнать, из какого именно дива произошел вызов. Вообще, JavaScript настолько качественно имплантирован в DOM и он так удобно позволяет перемещаться по его элементам, собирать нужную информацию, что динамика страницы может быть просто непредсказуемой.

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

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

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

О распределенном мышлении

Разработчику приходится мыслить на уровне всех элементов страницы, на уровне всех событий и иметь в ясном представлении, как все происходит на самом деле. Это сложно, но эта работа стоит того.

В JavaScript выполнение функции может быть отложено до какого-либо события, а таких функций может быть много, да и события имеют свойство распространяться и попадать в «сферу видимости» различных обработчиков.

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

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

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

Аргументы и результаты функций

JavaScript позволяет привести код к «полнофункциональному» состоянию. Нормально, когда аргументом функции является функция. Допускается вариант, когда функция возвращает функцию. JavaScript относится к этому совершенно спокойно.

Это хороший механизм, но достаточно сложный в отношении реализации. Технически все допустимо, семантически обеспечить логику передачи «функционала» под силу только квалифицированному разработчику.

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

Забота разработчика понятна и проста. Есть задача, нужно решение, а не ошибка вроде «JavaScript error the operation is insecure», чистый экран или остановка всего движка браузера.

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

Исполнение сформированного кода

Реализовать исполнение кода, сформированного в процессе работы другого кода, можно посредством «eval». Это не считается отличным решением, но часто можно не усложнять код излишними функциями, а ограничиться банальным формированием строки JavaScript кода и попросту исполнить ее.

В данном примере формируется строчка вставки в действующий див некоторой информации. Номер дива и содержание информации различны для различных позиций, потому такое решение в данной ситуации гарантированно не обеспечит ситуацию «javascript error the operation is insecure», но надежно даст нужный эффект.

Нюанс парадигмы JavaScript «функция в функции»

Если есть возможность обойтись без излишеств, лучше им воспользоваться. Все перечисленные варианты хороши. Безусловно, во многих случаях это единственное решение.

Классический пример рекурсии: вычисление факториала. Тут достаточно трудно написать алгоритм, который зациклится, но очень просто можно выйти за границы значения. Факториал растет слишком быстро.

Однако и рекурсия, и функция, вызывающая другую функцию, которая может сделать обоснованный обратный вызов - норма вещей.

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

Таких примеров можно привести множество, и все это будут реальные и насущные задачи, вовсе не из области программирования. Именно поэтому проблема заключается именно в том, что без излишеств не обойтись, созданная система функций, точнее ее отладка и последующая надежная работа становится заботой не JavaScript, а разработчика.

Статья в разработке!

Статья, в которой рассмотрим, что такое функция, а также традиционный (классический) вариант работы с ней. Кроме этого, разберем, что такое аргументы (параметры) функции и оператор return.

Что такое функция?

Функция - это некоторый набор инструкций , которому можно дать имя , а затем обратиться к нему по этому имени из любого места программы.

Классический пример использования функции. На веб-странице имеется код JavaScript, некоторый фрагмент в котором повторяется несколько раз . Чтобы этого избежать можно оформить этот фрагмент в виде функции , а затем вызывать его в нужных местах кода по имени этой функции . Вызов этой функции будет обозначать выполнение инструкций , находящихся в ней.

Как организовать выполнение некоторой задачи в JavaScript с использованием функций? Чтобы это выполнить обычно поступают так:

  • разбивают задачу на составные части (подзадачи);
  • подзадачи оформляют через функции;
  • разрабатывают основной код с использованием вызова созданных функций.

В результате такая программа становится более структурированной. В неё более просто вносить различные изменения и добавлять новые возможности.

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

Операции с функцией в JavaScript можно разделить на 2 шага:

  • объявление (создание) функции.
  • вызов (выполнение) этой функции.

Объявление функции. Создание функции в JavaScript начинается с написания ключевого слова function , далее указывается имя функции, затем в круглых скобка х при необходимости перечисляются параметры , после этого указываются инструкции , которые заключаются в фигурные скобки .

// объявление функции someName function someName() { alert("Вы вызвали функцию someName!"); } JavaScript - Синтаксис объявления функции

Функции такого вида в JavaScript называются function declaration statement . Кроме этого вида в JavaScript ещё различают функции function definition expression и arrow function expression .

Составление имени функции выполняется по тем же правилам, что и имя переменной. Т.е. оно может содержать буквы, цифры (0-9), знаки «$» и «_». В качестве букв рекомендуется использовать только буквы английского алфавита (a-z, A-Z). Имя функции, также как и имя переменной не может начинаться с цифры.

Параметров у функции может быть сколько угодно много или не быть вообще. Круглые скобки в любом случае указываются. Если параметров несколько, то их между собой необходимо разделить с помощью запятой . Обращение к параметрам функции осуществляется по их имени.

Набор инструкций , заключенный в фигурные скобки - это код функции , который будет выполнен при её вызове .

Вызов функции. Объявленная функция сама по себе выполняться не будет . Для того чтобы её запустить , её необходимо вызвать . Вызов функции осуществляется посредством указания её имени и двух круглых скобок. Внутри скобок при необходимости указываются аргументы.

// вызов функции, приведённой в предыдущем примере someName(); JavaScript - Синтаксис вызова функции

Является ли функция в JavaScript объектом?

Функции в JavaScript являются объектами. В JavaScript вообще всё является объектами, кроме шести примитивных типов данных. А если функция является объектом, то ссылку на неё можно сохранить в переменную.

// объявление функции someName function someName() { alert("Вы вызвали функцию someName!"); } var reference = someName;

После этого вызвать функцию можно будет так:

Reference();

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

Аргументы функции - это значения, которые передаются функции на этапе её вызова. Отделяются аргументы друг от друга с помощью запятой.

// вызов функции sayWelcome с передачей ей двух аргументов sayWelcome("Иван", "Иванов"); // ещё один вызов функции sayWelcome с двумя аргументами sayWelcome("Петр", "Петров");

Параметры функции – это один из способов в JavaScript, посредством которого можно обратиться к аргументам внутри функции. Описываются параметры функции на этапе её объявления в круглых скобках.

Другими словами параметры функции - это локальные переменные, которые создаются автоматически на этапе запуска функции. В качестве значений параметры получают соответствующие аргументы, переданные функции во время её вызова. Обратиться к параметрам можно только внутри этой функции, вне её они не существуют.

// объявление функции sayWelcome, которая имеет два параметра function sayWelcome (userFirstName, userLastName) { // инструкция, выводящая в консоль значения параметров «userFirstName» и «userLastName» console.log("Добро пожаловать, " + userLastName + " " + userFirstName); }

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

Например , вызовем функцию из примера, приведённого выше, без указания одного и двух параметров:

// вызов функции sayWelcome и передача ей одного аргумента sayWelcome("Петр"); // Добро пожаловать, undefined Петр // вызов функции sayWelcome без передачи ей аргументов sayWelcome(); // Добро пожаловать, undefined undefined

Пример функции, которая будет просто выводить переданные ей аргументы в консоль браузера:

// объявление функции function outputParam(param1, param2, param3) { console.log(param1 + "; " + param2 + "; " + param3); } // вызовы функции outputParam с передачей ей разного количества параметров outputParam("Дождь","Снег","Туман"); // Дождь; Снег; Туман outputParam(17); // 17; undefined; undefined outputParam(24,33); // 24; 33; undefined outputParam(); // undefined; undefined; undefined

Другой способ обратиться к аргументам внутри функции – это использовать специальный объект arguments . Доступ к аргументам через arguments выполняется точно также как к элементам обычного массива, т.е. по их порядковым номерам. Таким образом, argument - позволит получить первый аргумент, arguments – второй аргумент и т.д.

// объявление функции sum function sum(num1, num2) { /* num1 или arguments – получить значение 1 аргумента num2 или arguments – получить значение 2 аргумента */ var sum1 = num1 + num2, sum2 = arguments + arguments; return "Сумма, полученная 1 способом равна " + sum1 + "; сумма, полученная 2 способом равна " + sum2; } /* выведем результат функции sum в консоль 7 - первый аргумент (к нему можно обратиться как по имени num1, так и с помощью arguments) 4 - второй аргумент (к нему можно обратиться как по имени num2, так и с помощью arguments) */ console.log(sum(7,4));

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

Кроме получения аргументов, объект arguments позволяет также узнать их количество. Выполняется это с помощью свойства length.

Перебрать аргументы , переданные функции, можно, например, с помощью цикла for или for...of .

// объявление функции sum function sum() { var i = 0; console.log("Вывод всех аргументов с помощью цикла for"); for (i; i < arguments.length; i++) { console.log(i + 1 + " аргумент равен " + arguments[i]); } console.log("Вывод всех аргументов с помощью цикла for...of"); for (arg of arguments) { console.log(arg); } } // вызов функции sum sum(7, 4, 3, 1);

Функция, выводящая в консоль все переданные ей аргументы и их количество:

// объявление функции function myFunction () { var i; console.log("Количество переданных параметров = " + arguments.length); // переберём все параметры с помощью цикла for for (i = 0; i < arguments.length; i++) { console.log(i + " параметр = " + arguments[i]); } } // вызовы функции myFunction myFunction(3, 7, 27, "JavaScript"); myFunction(); myFunction("Яблоки", "Груши", "Апельсины");

Функция, выполняющая сложение все переданных ей аргументов (их количество заранее неизвестно):

// объявление функции var myCalc = function() { // переберём все параметры с помощью цикла for var i, sum = 0; for (i = 0; i lt; arguments.length; i++) { sum += arguments[i]; } // возвратим в качестве результата сумму return sum; } //вызов функции (вывод в консоль) console.log(myCalc(4, 20, 17, -6));

В результате, посредством объекта arguments можно реализовать в теле функции:

  • проверку количества переданных аргументов;
  • обработку какого угодного количества параметров.

Кроме самой функции, доступ к аргументам, которые передаются ей на этапе вызова, имеют также другие функции, находящиеся в ней.

Function mainF(p1, p2) { function childF() { console.log("p1 = " + p1 + "; p2 = " + p2); } childF(); } mainF(3, 5); // p1 = 3; p2 = 5 mainF(4, 7); // p1 = 4; p2 = 7

Значение параметров по умолчанию

Начиная с версии ECMAScript 2015 (6) параметру функции можно задать значение, которое он будет иметь по умолчанию.

Например , установим параметру «color» значение по умолчанию, равное «#009688»:

Function setBGColor(color = "#009688") { document.body.style.backgroundColor = color; } setBGColor(); // цвет фона будет равен #009688 setBGColor("red"); // цвет фона будет равен red

До ECMAScript 2015 задать параметру значение по умолчанию можно, например, было так:

Function setBGColor(color) { color = color !== undefined ? color: "#009688"; // устанавливаем color значение по умолчанию, равное "#009688" document.body.style.backgroundColor = color; }

Оставшиеся параметры (rest parameters)

Если при вызове функции ей передать аргументов больше, чем у неё есть параметров, то получить оставшиеся можно с помощью, так называемых оставшихся параметров (rest patameters) . Данная возможность в языке появилась, начиная с ECMAScript 2015.

// ...nums - оставшиеся параметры, к которым можно обратиться в данном случае по имени nums function doMath(mathAction, ...nums) { var result = 0; nums.forEach(function(value) { switch (mathAction) { case "sum": result += value; break; case "sumCube": result += value**3; break; case "sumSquare": result += value**2; break; deafult: result = 0; } }) return result; } console.log(doMath("sum", 3, 4, 21, -4)); // 24 (3 + 4 + 21 + (-4)) console.log(doMath("sumSquare", 1, 4)); // 17 (1^2 + 4^2) console.log(doMath("sumCube", 3, 2, 4)); // 99 (3^3 + 2^3 + 4^3)

Оператор return

Оператор return предназначен для возвращения значения или результата вычисления выражения текущей функции. Значение или выражение должно быть отделено от return посредством пробела. Кроме этого, оператор return прекращает выполнение функции, т.е. все инструкции, идущие после него, исполнены не будут.

Функция в JavaScript всегда возвращает результат в вне зависимости от того, используется ли оператор return или нет.

// функция, возвращающая результат function sayWelcome (userFirstName, userLastName) { if ((!userFirstName) || (!userLastName)) return "Добро пожаловать, анонимный пользователь"; else return "Добро пожаловать, " + userLastName + " " + userFirstName; } // объявление переменной person var person; // присвоить переменной person результат функции sayWelcome person = sayWelcome("Иван","Иванов"); // вывести значение переменной в консоль console.log(person); //Инструкция, которая выведит в консоль результат работы функции sayWelcome console.log(sayWelcome("Петр","Петров")); //Инструкция, которая выведит в консоль результат работы функции sayWelcome console.log(sayWelcome("Сидоров")); JavaScript - Функция с проверкой параметров

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

// 1. функция, не возвращающая никакого результата function sayWelcome (userFirstName, userLastName) { console.log("Добро пожаловать, " + userLastName + " " + userFirstName); } // попробуем получить результат у функции, которая ничего не возвращает console.log(sayWelcome ("Иван", "Иванов")); // 2. функция, содержащая оператор return без значения function sayDay (day) { day = "Сегодня, " + day; return; //эта инструкция не выполнится, т.к. она идёт после оператора return console.log(day); } // попробуем получить результат у функции, которая содержит оператор return без значения console.log(sayDay("21 февраля 2016г.")); JavaScript - Получить значение у функции, которая ничего не возвращает

Такой же результат будет получен, если для оператора return не указать возвращаемое значение.

Перегрузка функций в JavaScript

Перегрузка функций в программировании – это возможность объявлять несколько функций с одинаковыми именами в одной области видимости. Отличаются такие функции друг от друга типом и числом аргументов. Каждая функция имеет свою программную логику. Используется перегрузка функций для того, чтобы с помощью одного имени функции можно было выполнять близкие действия.

Язык JavaScript не поддерживает перегрузку функций в том виде, как это реализовано, например, в Си подобных языках. Т.е. в JavaScript нельзя создать несколько функций с одинаковыми именами, находящихся в одной области видимости.

Подобную функциональность можно реализовать в JavaScript используя следующие действия:

  • Для того чтобы проверить передан аргумент или нет, используйте условие с проверкой его значения на undefined .
  • Для проверки количества переданных аргументов функции используйте свойство объекта arguments length .
  • Чтобы узнать тип переданного значения аргумента используйте операторы typeof или instanceof .
  • Для работы с переменным числом аргументов, используйте объект arguments .
  • Начиная с версии ECMAScript6, Вы можете указывать значения по умолчанию для аргументов.

Например, создадим функцию, при вызове которой можно указывать один или два аргумента:

//объявление функции, которая изменяет цвет заднего фона элементов function setBgColor(bgColor,elements) { //если параметр elements при вызове не указан if (elements=== undefined) { //то приравнять его значение "div" elements = "div"; } //получить все элементы elements = $(elements); //перебрать все элементы и установить им указанный цвет заднего фона elements.each(function(){ $(this).css("background-color",bgColor); }); } /*Вызвать функцию setBgColor, указав один параметр. Т.к. 2 параметр не указан, то данная фукция изменит цвет заднего фона у всех элементов div.*/ setBgColor("green"); /*Вызвать функцию setBgColor, указав 2 параметра. Т.к. 2 параметр задан, то данная функция изменит цвет заднего фона только элементов button.*/ setBgColor("#ff0000","button");

Произведём некоторые изменения в вышепредставленном коде. А именно, укажем для второго параметра значение по умолчанию:

//объявление функции, которая изменяет цвет заднего фона элементов //параметр elements имеет значение "div" по умолчанию function setBgColor(bgColor,elements = "div") { //получить все элементы elements = $(elements); //перебрать все элементы и установить им указанный цвет заднего фона elements.each(function(){ $(this).css("background-color",bgColor); }); } //вызвать функцию setBgColor, указав один параметр setBgColor("green"); //вызвать функцию setBgColor, указав 2 параметра setBgColor("#ff0000","button");

Пример, как в JavaScript можно реализовать «перегруженную» функцию, вычисляющую количество калорий, которых необходимо человеку в день:

// описание функции function countCal(sex, height) { // параметры: sex (пол) и height (рост) var result; if ((sex === 0) || (sex === "man")) { result = (height - 100) * 20; } else if ((sex === 1) || (sex === "woman")) { result = (height - 105) * 19; } if (result) { // arguments - уровень активности if (arguments) { result *= arguments; } console.log("Количество ккал для нормальной жизнедеятельности: " + result); } else { console.log("Неверно указаны параметры"); } } /* вызов функции и передаче ей 2 аргументов (1 - "man", к нему можно обратиться с помощью имени sex и arguments; 2 - значение 185, к нему можно обратиться с помощью имени sex и arguments) */ countCal("man", 185); /* вызов функции и передаче ей 3 параметров, хотя в описании функции присутствуют только 2 (получить значение 3 параметра в данном случае можно только как arguments) */ countCal(0, 185, 2);

Рекурсия

Рекурсия – это вызов внутри тела некоторой функции самой себя.

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

Function fact(n) { if (n === 1) { return 1; } return fact(n-1) * n; } console.log(fact(5)); // 120

Вызвать функцию внутри её тела можно не только по имени, но также с помощью свойства callee объекта arguments. Но данное свойство лучше не использовать, т.к. оно является устаревшим. Кроме этого в строгом режиме оно вообще не работает.

Что такое встроенные (стандартные) функции?

В JavaScript имеется огромный набор встроенных (стандартных) функций. Данные функции уже описаны в самом движке браузера. Практически все они являются методами того или иного объекта.

Например, для того чтобы вызвать встроенную функцию (метод) alert, её не надо предварительно объявлять. Она уже описана в браузере. Вызов метода alert осуществляется посредством указания имени, круглых скобок и аргумента внутри них. Данный метод предназначен для вывода сообщения на экран в форме диалогового окна. Текстовое сообщение берётся из значения параметра данной функции.

// вызов функции alert alert("Некоторый текст"); JavaScript - Вызов функции alert

В этой статье описаны функции Javascript на уровне языка: создание, параметры, приемы работы, замыкания и многое другое.

Создание функций

Существует 3 способа создать функцию. Основное отличие в результате их работы - в том, что именованная функция видна везде, а анонимная - только после объявления:

Функции - объекты

В javascript функции являются полноценными объектами встроенного класса Function. Именно поэтому их можно присваивать переменным, передавать и, конечно, у них есть свойства:

Function f() { ... } f.test = 6 ... alert(f.test) // 6

Свойства функции доступны и внутри функции, так что их можно использовать как статические переменные.

Например,

Function func() { var funcObj = arguments.callee funcObj.test++ alert(funcObj.test) } func.test = 1 func() func()

В начале работы каждая функция создает внутри себя переменную arguments и присваивает arguments.callee ссылку на себя. Так что arguments.callee.test - свойство func.test , т.е статическая переменная test.

В примере нельзя было сделать присвоение:

Var test = arguments.callee.test test++

так как при этом операция ++ сработала бы на локальной переменной test , а не на свойстве test объекта функции.

Объект arguments также содержит все аргументы и может быть преобразован в массив (хотя им не является), об этом - ниже, в разделе про параметры.

Области видимости

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

Переменные можно объявлять в любом месте. Ключевое слово var задает переменную в текущей области видимости. Если его забыть, то переменная попадет в глобальный объект window . Возможны неожиданные пересечения с другими переменными окна, конфликты и глюки.

В отличие от ряда языков, блоки не задают отдельную область видимости. Без разницы - определена переменная внутри блока или вне его. Так что эти два фрагмента совершенно эквивалентны:

Заданная через var переменная видна везде в области видимости, даже до оператора var . Для примера сделаем функцию, которая будет менять переменную, var для которой находится ниже.

Например:

Function a() { z = 5 // поменяет z локально.. // .. т.к z объявлена через var var z } // тест delete z // очистим на всякий случай глобальную z a() alert(window.z) // => undefined, т.к z была изменена локально

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

Функции можно запускать с любым числом параметров.

Если функции передано меньше параметров, чем есть в определении, то отсутствующие считаются undefined .

Следующая функция возвращает время time , необходимое на преодоление дистанции distance с равномерной скоростью speed .

При первом запуске функция работает с аргументами distance=10 , speed=undefined . Обычно такая ситуация, если она поддерживается функцией, предусматривает значение по умолчанию:

// если speed - ложное значение(undefined, 0, false...) - подставить 10 speed = speed || 10

Оператор || в яваскрипт возвращает не true/false , а само значение (первое, которое приводится к true).

Поэтому его используют для задания значений по умолчанию. В нашем вызове speed будет вычислено как undefined || 10 = 10 .

Поэтому результат будет 10/10 = 1 .

Второй запуск - стандартный.

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

Ну и в последнем случае аргументов вообще нет, поэтому distance = undefined , и имеем результат деления undefined/10 = NaN (Not-A-Number, произошла ошибка).

Работа с неопределенным числом параметров

Непосредственно перед входом в тело функции, автоматически создается объект arguments , который содержит

  • Аргументы вызова, начиная от нуля
  • Длину в свойстве length
  • Ссылку на саму функцию в свойстве callee
  • Например,

    Function func() { for(var i=0;i alert(3)

    Пример передачи функции по ссылке

    Функцию легко можно передавать в качестве аргумента другой функции.

    Например, map берет функцию func , применяет ее к каждому элементу массива arr и возвращает получившийся массив:

    Var map = function(func, arr) { var result = for(var i=0; i [ window, "one", "two" ]
    Погодите. Откуда взялся объект window ? Почему это у нас this равен window ?

    В JavaScript, неважно, выполняется ли скрипт в браузере или в ином окружении, всегда определен глобальный объект . Любой код в нашем скрипте, не «привязанный» к чему-либо (т.е. находящийся вне объявления объекта) на самом деле находится в контексте глобального объекта. В нашем случае, makeArray - не просто функция, «гуляющая» сама по себе. На самом деле, makeArray - метод глобального объекта (в случае исполнения кода в браузере) window . Доказать это легко:
    alert(typeof window.methodThatDoesntExist); // => undefined alert(typeof window.makeArray); // => function
    То есть вызов makeArray("one", "two"); равносилен вызову window.makeArray("one", "two"); .

    Меня печалит тот факт, что этот способ вызова функций наиболее распространен, ведь он подразумевает наличие глобальной функции. А мы все знаем, что глобальные функции и переменные - не самый хороший тон в программировании. Особенно это справедливо для JavaScript. Избегайте глобальных определений, и не пожалеете.

    Правило вызова функций №1: Если функция вызывается напрямую, без указания объекта (например, myFunction()), значением this будет глобальный объект (window в случае исполнения кода в браузере).

    Вызов метода Давайте создадим простой объект и сделаем makeArray его методом. Объект объявим с помощью литеральной нотации, а после вызовем наш метод:
    // создаем объект var arrayMaker = { someProperty: "какое-то значение", make: makeArray }; // вызываем метод make() arrayMaker.make("one", "two"); // => [ arrayMaker, "one", "two" ] // альтернативный синтаксис, используем квадратные скобки arrayMaker["make"]("one", "two"); // => [ arrayMaker, "one", "two" ]
    Видите разницу? Значение this в этом случае - сам объект. Почему не window , как в предыдущем случае, ведь объявление функции не изменилось? Весь секрет в том, как передаются функции в JavaScript. Function - это стандартный тип JavaScript, являющийся на самом деле объектом, и как и любой другой объект, функции можно передавать и копировать. В данном случае, мы как бы скопировали всю функцию, включая список аргументов и тело, и присвоили получившийся объект свойству make объекта arrayMaker . Это равносильно такому объявлению:
    var arrayMaker = { someProperty: "Какое-то значение"; make: function (arg1, arg2) { return [ this, arg1, arg2]; } };
    Правило вызова функций №2: В функции, вызванной с использованием синтаксиса вызова метода, например, obj.myFunction() или obj["myFunction"]() , this будет иметь значение obj .

    Непонимание этого простого, в общем-то, принципа часто приводит к ошибкам при обработке событий:
    function buttonClicked(){ var text = (this === window) ? "window" : this.id; alert(text); } var button1 = document.getElementById("btn1"); var button2 = document.getElementById("btn2"); button1.onclick = buttonClicked; button2.onclick = function(){ buttonClicked(); };
    Щелчок по первой кнопке покажет сообщение «btn1» , потому что в данном случае мы вызываем функцию как метод, и this внутри функции получит значение объекта, которому этот метод принадлежит. Щелчок по второй кнопке выдаст «window» , потому что в этом случае мы вызываем buttonClicked напрямую (т.е. не как obj.buttonClicked()). То же самое происходит, когда мы назначаем обработчик события в тэге элемента, как в случае третьей кнопки. Щелчок по третьей кнопке покажет то же самое сообщение, что и для второй.

    При использовании библиотек вроде jQuery думать об этом не надо. jQuery позаботится о том, чтобы переписать значение this в обработчике события так, чтобы значением this был элемент, вызвавший событие:
    // используем jQuery $("#btn1").click(function() { alert(this.id); // jQuery позаботится о том, чтобы "this" являлась кнопкой });
    Каким образом jQuery удается изменить значение this ? Читайте ниже.

    Еще два способа: apply() и call() Логично, что чем чаще вы используете функции, тем чаще вам приходится передавать их и вызывать в разных контекстах. Зачастую возникает необходимость переопределить значение this . Если вы помните, функции в JavaScript являются объектами. На практике это означает, что у функций есть предопределенные методы. apply() и call() - два из них. Они позволяют переопределять значение this:
    var car = { year: 2008, model: "Dodge Bailout" }; makeArray.apply(car, [ "one", "two" ]); // => [ car, "one", "two" ] makeArray.call(car, "one", "two"); // => [ car, "one", "two" ]
    Эти два метода очень похожи. Первый параметр переопределяет this . Различия между ними заключаются в последющих аргументах: Function.apply() принимает массив значений, которые будут переданы функции, а Function.call() принимает аргументы раздельно. На практике, по моему мнению, удобнее применять apply() .

    Правило вызова функций №3: Если требуется переопределить значение this , не копируя функцию в другой объект, можно использовать myFunction.apply(obj) или myFunction.call(obj) .

    Конструкторы Я не буду подробно останавливаться на объявлении собственных типов в JavaScript, но считаю необходимым напомнить, что в JavaScript нет классов, а любой пользовательский тип нуждается в конструкторе. Кроме того, методы пользовательского типа лучше объявлять через prototype , который является свойством фукции-конструктора. Давайте создадим свой тип:
    // объявляем конструктор function ArrayMaker(arg1, arg2) { this.someProperty = "неважно"; this.theArray = [ this, arg1, arg2 ]; } // объявляем методы ArrayMaker.prototype = { someMethod: function () { alert("Вызван someMethod"); }, getArray: function () { return this.theArray; } }; var am = new ArrayMaker("one", "two"); var other = new ArrayMaker("first", "second"); am.getArray(); // => [ am, "one", "two" ]
    Важным в этом примере является наличие оператора new перед вызовом функции. Если бы не он, это был бы глобальный вызов, и создаваемые в конструкторе свойства относились бы к глобальному объекту. Нам такого не надо. Кроме того, в конструкторах обычно не возвращают значения явно. Без оператора new конструктор вернул бы undefined , с ним он возвращает this . Хорошим стилем считается наименование конструкторов с заглавной буквы; это позволит вспомнить о необходимости оператора new .

    В остальном, код внутри конструктора, скорее всего, будет похож на код, который вы написали бы на другом языке. Значение this в данном случае - это новый объект, который вы создаете.

    Правило вызова функций №4: При вызове функции с оператором new , значением this будет новый объект, созданный средой исполнения JavaScript. Если эта функция не возвращает какой-либо объект явно, будет неявно возвращен this .

    Заключение Надеюсь, понимание разницы между разными способами вызова функций возволит вам улучшить ваш JavaScript-код. Иногда непросто отловить ошибки, связанные со значением this , поэтому имеет смысл предупреждать их возникновение заранее.

    Функции

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

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

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

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

    Определение функций

    Определение функции начинается с ключевого слова function , за которым указываются следующие компоненты:

    Идентификатор, определяющий имя функции

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

    Пара круглых скобок вокруг списка из нуля или более идентификаторов, разделенных запятыми

    Эти идентификаторы будут определять имена параметров функции и в теле функции могут использоваться как локальные переменные.

    Пара фигурных скобок с нулем или более инструкций JavaScript внутри

    Эти инструкции составляют тело функции: они выполняются при каждом вызове функции.

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

    // Выводит имена и значения всех свойств объекта obj function printprops(obj) { for(var p in obj) console.log(p + ": " + obj[p] + "\n"); } // Вычисляет расстояние между точками (x1,y1) и (x2,y2) function distance(x1, y1, x2, y2) { var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx*dx + dy*dy); } // Рекурсивная функция (вызывающая сама себя), вычисляющая факториал function factorial(x) { if (x

    Обратите внимание, что в выражениях определения функций имя функции может отсутствовать. Инструкция объявления функции фактически объявляет переменную и присваивает ей объект функции.

    Выражение определения функции, напротив, не объявляет переменную. Однако в выражениях определения допускается указывать имя функции, как в функции вычисления факториала выше, которое может потребоваться в теле функции для вызова себя самой. Если выражение определения функции включает имя, данное имя будет ссылаться на объект функции в области видимости этой функции. Фактически имя функции становится локальной переменной, доступной только в теле функции. В большинстве случаев имя функции не требуется указывать в выражениях определения, что делает определения более компактными.

    Обратите внимание, что большинство (но не все) функций в примере содержат инструкцию return. Инструкция return завершает выполнение функции и выполняет возврат значения своего выражения (если указано) вызывающей программе. Если выражение в инструкции return отсутствует, она возвращает значение undefined. Если инструкция return отсутствует в функции, интерпретатор просто выполнит все инструкции в теле функции и вернет вызывающей программе значение undefined.

    Большинство функций в примере вычисляют некоторое значение, и в них инструкция return используется для возврата этого значения вызывающей программе. Функция printprops() несколько отличается в этом смысле: ее работа заключается в том, чтобы вывести имена свойств объекта. Ей не нужно возвращать какое-либо значение, поэтому в функции отсутствует инструкция return. Функция printprops() всегда будет возвращать значение undefined. (Функции, не имеющие возвращаемого значения, иногда называются процедурами.)

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

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

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

    Printprops({x:4, age: 24}); var d = distance(1,1,5,6); var f = factorial(5) / factorial(12); f = square(5);

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

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

    Метод - это не что иное, как функция, которая хранится в виде свойства объекта. Если имеется функция func и объект obj, то можно определить метод объекта obj с именем method, как показано ниже:

    // Определим простой объект и функцию var obj = {}; function func(a, b) { return a+b;} // Добавим в объект obj метод obj.method = func; // Теперь можно вызвать этот метод var result = obj.method(4, 5);

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

    Result = obj.method(4, 5); result = obj["method"](4, 5);

    Аргументы и возвращаемое значение при вызове метода обрабатываются точно так же, как при вызове обычной функции. Однако вызов метода имеет одно важное отличие: контекст вызова. Выражение обращения к свойству состоит из двух частей: объекта (в данном случае obj) и имени свойства (method). В подобных выражениях вызова методов объект obj становится контекстом вызова, и тело функции получает возможность ссылаться на этот объект с помощью ключевого слова this. Например:

    Var obj = { x: 0, y: 0, // Метод add: function(a, b) { this.x = a; this.y = b; }, // Еще один метод sum: function() { return this.x + this.y } }; // Вызов методов obj.add(15, 4); console.log(obj.sum()); // 19

    Методы и ключевое слово this занимают центральное место в парадигме объектно-ориентированного программирования. Любая функция, используемая как метод, фактически получает неявный аргумент - объект, относительно которого она была вызвана. Как правило, методы выполняют некоторые действия с объектом, и синтаксис вызова метода наглядно отражает тот факт, что функция оперирует объектом.

    Обратите внимание: this - это именно ключевое слово, а не имя переменной или свойства. Синтаксис JavaScript не допускает возможность присваивания значений элементу this.

    Аргументы и параметры функций

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

    Необязательные аргументы

    Когда число аргументов в вызове функции меньше числа объявленных параметров, недостающие аргументы получают значение undefined. Часто бывает удобным писать функции так, чтобы некоторые аргументы были необязательными и могли опускаться при вызове функции. В этом случае желательно предусмотреть возможность присваивания достаточно разумных значений по умолчанию параметрам, которые могут быть опущены. Например:

    // Добавить в массив arr перечислимые имена // свойств объекта obj и вернуть его. Если аргумент // arr не не был передан, создать и вернуть новый массив function getPropertyNames(obj, /* необязательный */ arr) { if (arr === undefined) arr = ; // Если массив не определен, создать новый for(var property in obj) arr.push(property); return arr; } // Эта функция может вызываться с 1 или 2 аргументами: var a = getPropertyNames({x:1, y:1}); // Получить свойства объекта в новом массиве getPropertyNames({z:5},a); // добавить свойства нового объекта в этот массив console.log(a); // ["x", "y", "z"]

    Обратите внимание, что при объявлении функций необязательные аргументы должны завершать список аргументов, чтобы их можно было опустить. Программист, который будет писать обращение к вашей функции, не сможет передать второй аргумент и при этом опустить первый: он будет вынужден явно передать в первом аргументе значение undefined. Обратите также внимание на комментарий /* необязательный */ в определении функции, который подчеркивает тот факт, что параметр является необязательным.

    Списки аргументов переменной длины

    Если число аргументов в вызове функции превышает число имен параметров, функция лишается возможности напрямую обращаться к неименованным значениям. Решение этой проблемы предоставляет объект Arguments . В теле функции идентификатор arguments ссылается на объект Arguments, присутствующий в вызове. Объект Arguments - это объект, подобный массиву, позволяющий извлекать переданные функции значения по их номерам, а не по именам.

    Предположим, что была определена функция func, которая требует один аргумент x. Если вызвать эту функцию с двумя аргументами, то первый будет доступен внутри функции по имени параметра x или как arguments. Второй аргумент будет доступен только как arguments. Кроме того, подобно настоящим массивам, arguments имеет свойство length, определяющее количество содержащихся элементов. То есть в теле функции func, вызываемой с двумя аргументами, arguments.length имеет значение 2.

    Объект Arguments может использоваться с самыми разными целями. Следующий пример показывает, как с его помощью проверить, была ли функция вызвана с правильным числом аргументов, - ведь JavaScript этого за вас не сделает:

    Function func(x, y, z) { // Сначала проверяется, правильное ли количество аргументов передано if (arguments.length != 3) { throw new Error("Функция func вызвана с " + arguments.length + " аргументами, а требуется 3."); } // А теперь сам код функции... }

    Обратите внимание, что зачастую нет необходимости проверять количество аргументов, как в данном примере. Поведение по умолчанию интерпретатора JavaScript отлично подходит для большинства случаев: отсутствующие аргументы замещаются значением undefined, а лишние аргументы просто игнорируются.

    Объект Arguments иллюстрирует важную возможность JavaScript-функций: они могут быть написаны таким образом, чтобы работать с любым количеством аргументов. Следующая функция принимает любое число аргументов и возвращает значение самого большого из них (аналогично ведет себя встроенная функция Math.max()):

    Function maxNumber() { var m = Number.NEGATIVE_INFINITY; // Цикл по всем аргументам, поиск и // сохранение наибольшего из них for(var i = 0; i m) m = arguments[i]; // Вернуть наибольшее значение return m; } var largest = maxNumber(1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6); // 10000

    Функции, подобные этой и способные принимать произвольное число аргументов, называются функциями с переменным числом аргументов (variadic functions, variable arity functions или varargs functions) . Этот термин возник вместе с появлением языка программирования C.

    Обратите внимание, что функции с переменным числом аргументов не должны допускать возможность вызова с пустым списком аргументов. Будет вполне разумным использовать объект arguments при написании функции, ожидающей получить фиксированное число обязательных именованных аргументов, за которыми может следовать произвольное число необязательных неименованных аргументов.

    Не следует забывать, что arguments фактически не является массивом - это объект Arguments. В каждом объекте Arguments имеются пронумерованные элементы массива и свойство length, но с технической точки зрения это не массив. Лучше рассматривать его как объект, имеющий некоторые пронумерованные свойства.

    Помимо элементов своего массива объект Arguments определяет свойства callee и caller . При попытке изменить значения этих свойств в строгом режиме ECMAScript 5 гарантированно возбуждается исключение TypeError. Однако в нестрогом режиме стандарт ECMAScript утверждает, что свойство callee ссылается на выполняемую в данный момент функцию. Свойство caller не является стандартным, но оно присутствует во многих реализациях и ссылается на функцию, вызвавшую текущую.

    Свойство caller можно использовать для доступа к стеку вызовов, а свойство callee особенно удобно использовать для рекурсивного вызова неименованных функций:

    Var factorial = function(x) { if (x

    Свойства и методы функций

    Мы видели, что в JavaScript-программах функции могут использоваться как значения. Оператор typeof возвращает для функций строку «function», однако в действительности функции в языке JavaScript - это особого рода объекты. А раз функции являются объектами, то они имеют свойства и методы, как любые другие объекты. Существует даже конструктор Function(), который создает новые объекты функций. В следующих подразделах описываются свойства и методы функций.

    Свойство length

    В теле функции свойство arguments.length определяет количество аргументов, переданных функции. Однако свойство length самой функции имеет иной смысл. Это свойство, доступное только для чтения, возвращает количество аргументов, которое функция ожидает получить - число объявленных параметров.

    В следующем фрагменте определяется функция с именем check(), получающая массив аргументов arguments от другой функции. Она сравнивает свойство arguments.length (число фактически переданных аргументов) со свойством arguments.callee.length (число ожидаемых аргументов), чтобы определить, передано ли функции столько аргументов, сколько она ожидает. Если значения не совпадают, генерируется исключение. За функцией check() следует тестовая функция func(), демонстрирующая порядок использования функции check():

    // Эта функция использует arguments.callee, поэтому она // не будет работать в строгом режиме function check(args) { var actual = args.length; // Фактическое число аргументов var expected = args.callee.length; // Ожидаемое число аргументов if (actual !== expected) // Если не совпадают, генерируется исключение throw new Error("ожидается: " + expected + "; получено " + actual); } function func(x, y, z) { // Проверить число ожидаемых и фактически переданных аргументов check(arguments); // Теперь выполнить оставшуюся часть функции return x + y + z; }

    Свойство prototype

    Любая функция имеет свойство prototype, ссылающееся на объект, известный как объект прототипа. Каждая функция имеет свой объект прототипа. Когда функция используется в роли конструктора, вновь созданный объект наследует свойства этого объекта прототипа.

    Прототипы и свойство prototype обсуждались в предыдущей статье.

    Методы call() и apply()

    Методы call() и apply() позволяют выполнять косвенный вызов функции, как если бы она была методом некоторого другого объекта. Первым аргументом обоим методам, call() и apply(), передается объект, относительно которого вызывается функция; этот аргумент определяет контекст вызова и становится значением ключевого слова this в теле функции. Чтобы вызвать функцию func() (без аргументов) как метод объекта obj, можно использовать любым из методов, call() или apply():

    Func.call(obj); func.apply(obj);

    Любой из этих способов вызова эквивалентен следующему фрагменту (где предполагается, что объект obj не имеет свойства с именем m):

    Obj.m = func; // Временно сделать func методом obj obj.m(); // Вызывать его без аргументов. delete obj.m; // Удалить временный метод.

    В строгом режиме ECMAScript 5 первый аргумент методов call() и apply() становится значением this, даже если это простое значение, null или undefined. В ECMAScript 3 и в нестрогом режиме значения null и undefined замещаются глобальным объектом, а простое значение - соответствующим объектом-оберткой.

    Все остальные аргументы метода call(), следующие за первым аргументом, определяющим контекст вызова, передаются вызываемой функции. Метод apply() действует подобно методу call(), за исключением того, что аргументы для функции передаются в виде массива. Если функция способна обрабатывать произвольное число аргументов, метод apply() может использоваться для вызова такой функции в контексте массива произвольной длины.

    В следующем примере демонстрируется практическое применение метода call():

    // Ниже определены две функции, отображающие свойства и // значения свойств произвольного объекта. Способ // отображения передаются в виде аргумента func function print1(func, obj) { for (n in obj) func(n +": " + obj[n]); } function print2(func, objDevice, obj) { for (n in obj) func.call(objDevice, n +": " + obj[n]); } var obj = {x:5, y:10}; print2(document.write, document, obj); // Работает корректно print2(console.log, console, obj); print1(document.write, obj); // Возникнет исключение Illegal invocation, т.к. print1(console.log, obj); // невозможно вызвать эти методы без объекта контекста

    Метод bind()

    Метод bind() впервые появился в ECMAScript 5, но его легко имитировать в ECMAScript 3. Как следует из его имени, основное назначение метода bind() состоит в том, чтобы связать (bind) функцию с объектом. Если вызвать метод bind() функции func и передать ему объект obj, он вернет новую функцию. Вызов новой функции (как обычной функции) выполнит вызов оригинальной функции func как метода объекта obj. Любые аргументы, переданные новой функции, будут переданы оригинальной функции. Например:

    // Функция, которую требуется привязать function func(y) { return this.x + y; } var obj = {x:1}; // Объект, к которому выполняется привязка var g = func.bind(obj); // Вызов g(x) вызовет obj.func(x)

    Такой способ связывания легко реализовать в ECMAScript 3, как показано ниже:

    // Возвращает функцию, которая вызывает func как метод объекта obj // и передает ей все свои аргументы function bind(func, obj) { if (func.bind) return func.bind(obj); // Использовать метод bind, если имеется else return function() { // Иначе связать, как показано ниже return func.apply(obj, arguments); }; }

    Метод bind() в ECMAScript 5 не просто связывает функцию с объектом. Он также выполняет частичное применение: помимо значения this связаны будут все аргументы, переданные методу bind() после первого его аргумента. Частичное применение - распространенный прием в функциональном программировании и иногда называется каррингом (currying) .



    Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: