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

Статья, в которой рассмотрим, что такое функция, а также традиционный (классический) вариант работы с ней. Кроме этого, разберем, что такое аргументы (параметры) функции и оператор 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 поддерживает концепцию ООП (объектное ориентированное программирование). Это концепция состоит в том, что существуют такие элементы как объекты и у этих объектов есть различные свойства и методы(функции), которые позволяют управлять ими.

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

Метод - это тоже функция, но, он принадлежит уже какому-то классу или объекту.

Для того чтобы вызывать какой-то метод , необходимо сначала написать название объекта, потом через точку написать название метода. Исключением этого правила является вызов методов alert(), confirm() и prompt() объекта window. Их можно вызывать без того чтобы указать название объекта. С этими методами мы уже познакомились в этой статье .

Также, в предыдущих статьях мы познакомились с методом вывода document.write() , который принадлежит объекту document.

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

Синтаксис функции выглядит таким образом:


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

Function writeText(text){ //Добавляем текст в абзаце и выводим его document.write("

" + text + "

"); } //Вызов созданной функции writeText("Здравствуйте!");

Сохраняем документ и открываем его в браузере.


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

Для чего нужны функции в программировании?

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

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

//объявляем три массива var arr1 = ; var arr2 = ["b", 5, 9.2, "h", 8, 2]; var arr2 = ; for(var i = 0; i < arr1.length; i++){ document.write("

Элемент массива arr1, с индексом " + i + " равен: "+ arr1[i] +"

"); } for(var i = 0; i < arr2.length; i++){ document.write("

Элемент массива arr2, с индексом " + i + " равен: "+ arr2[i] +"

"); } for(var i = 0; i < arr3.length; i++){ document.write("

Элемент массива arr3, с индексом " + i + " равен: "+ arr3[i] +"

"); }

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

Function printArr(arr){ for(var i = 0; i < arr.length; i++){ document.write("

Элемент массива, с индексом " + i + " равен: "+ arr[i] +"

"); } } //объявляем три массива var arr1 = ; var arr2 = ["b", 5, 9.2, "h", 8, 2]; var arr2 = ; //Вызываем созданную функцию, для перебора каждого массива printArr(arr1); printArr(arr2); printArr(arr3);

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

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

Давайте создадим функцию без параметров , которая просто выведет на экран, классическую фразу "Hello world".

Function helloWorld(){ document.write("Hello World"); } //Вызываем функцию без параметров, helloWorld helloWorld();

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

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

Function summa(number1, number2 = 4){ document.write("

Сумма чисел " + number1 + "(Первый параметр) и " + number2 + "(Второй параметр) равна: " + (number1 + number2) + "

"); } //Вызываем функцию, которая, по умолчанию выведет результат сложения переданного числа, с цифрой 4. summa(5); // Результат: 9 //Если предадим и второй параметр, то функция выведет результат сложения чисел из обоих параметров. summa(5, 20); // Результат: 25

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

Для примера, вызовем первую созданную нами функцию writeText() внутри предыдущей функции summa(). Функции writeText() передадим результат сложения чисел. В таком случае код функции summa() будет выглядеть уже так:

Function summa(number1, number2 = 4){ writeText(number1 + number2); } //Вызываем функцию summa summa(5); // Результат: 9 summa(5, 20); // Результат: 25

Функции которые возвращают какое-то значение

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

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

Для того чтобы лучше понять о чем идёт речь, вспомним такие методы как prompt() и confirm(). Эти методы именно возвращают значение, полученное от пользователя, а не выводят его.

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

Function lastElement(arr){ //Возвращаем последний элемент переданного массива return arr; } //Объявляем массив var otherArr = ["iphone", "asus", 2000, 9.8, "twix"]; //Вызываем созданную функцию lastElement и в качестве параметра передаем ей созданный массив otherArr var lastEl = lastElement(otherArr); //Выводим полученный последний элемент массива alert(lastEl);

В результате мы получим слово ‘twix’, так как именно это слово и есть последний элемент массива otherArr.

Метод alert() ничего не возвращает . То есть если мы попытаемся выводить переменную которая типа содержит результат вызова метода alert(), то увидим значение undefined . Это тоже самое как попытаться выводить значение пустой переменной.

Для примера возьмём результат последнего вызова alert() из предыдущего примера, помещаем его в переменную resAlert и используя созданную нами функцию writeText, попытаемся вывести полученный результат.

//Выводим полученный последний элемент массива var resAlert = alert(lastEl); var test; writeText(resAlert); //undefined writeText(test); //undefined

Как видим в обоих случаях получили значение undefined.

Глобальные и локальные переменные

Глобальные переменные - это те переменные, которые объявлены за пределами функции. То есть все те переменные, которые не объявлены внутри самой функции, являются глобальными . Они видны (действительны) во всем документе.

Локальные переменные - это те переменные, которые объявлены внутри самой функции . И они действительны только внутри данной функции. За её пределами, локальные переменные уже не будут работать.

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


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

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

Вызываем функцию other(), и если теперь попробуем вывести значение переменной x, то в результате увидим цифру 4.

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

Var x = 8; function increment(){ x++; } //Вызываем функцию increment() increment(); alert(x); //Результат: 9

Если мы не хотим, чтобы глобальная переменная изменилась, необходимо объявить локальную переменную (можно с таким же именем, как и у глобальной) и все действия будут произведены над ней.

Var g = 100; function func(){ var g = 14; g *= 2; // Это тоже самое что g = g * 2 alert(g);//Результат: 28 } //Вызываем функцию. func(); alert(g);//Результат: 100

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

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

Задачи
  • Создайте функцию, которая принимает в качестве параметров две числа и возвращает результат умножения этих чисел.
  • Выведите полученный результат.
  • В этой статье описаны функции 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-кодом, ошибки в котором вызваны неправильным понимаем того, как работают функции в JavaScript (кстати, значительная часть такого кода была написана мной самим). JavaScript - язык мультипарадигменный, и в нем имеются механизмы функционального программирования. Пора изучить эти возможности. В этой статье я расскажу вам о пяти способах вызова функций в JavaScript.

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

    Давайте напишем простую функцию, которая возвращает массив из трех элементов - текущего значения this и двух аргументов, переданных в функцию.
    function makeArray(arg1, arg2){ return [ this, arg1, arg2 ]; }

    Самый распространенный способ: глобальный вызов Новички часто объявляют функции так, как показано в примере выше. Вызвать эту функцию не составляет труда:
    makeArray("one", "two"); // => [ 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 , поэтому имеет смысл предупреждать их возникновение заранее.