Перейти к содержимому

Какие функции выполняет javascript

  • автор:

Функции

— это блок программного кода на языке 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 // Следующее выражение определяет функцию, вычисляющую // квадрат аргумента. Обратите внимание, // что она присваивается переменной var square = function(x) < return x*x; >// Выражения определения функций могут иметь имена, что позволяет // производить рекурсивные вызовы var f = function fact(x) < if (x ; // Выражения определения функций иногда могут тут же вызываться: var tensquared = (function(x) (10));

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

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

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

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

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

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

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

printprops(); 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(); // Получить свойства объекта в новом массиве getPropertyNames(,a); // добавить свойства нового объекта в этот массив console.log(a); // ['x', 'y', 'z']

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

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

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

Предположим, что была определена функция func, которая требует один аргумент x. Если вызвать эту функцию с двумя аргументами, то первый будет доступен внутри функции по имени параметра x или как arguments[0]. Второй аргумент будет доступен только как arguments[1]. Кроме того, подобно настоящим массивам, 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 < arguments.length; i++) if (arguments[i] >m) m = arguments[i]; // Вернуть наибольшее значение return m; > var largest = maxNumber(1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6); // 10000

Функции, подобные этой и способные принимать произвольное число аргументов, называются . Этот термин возник вместе с появлением языка программирования 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 = ; 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 = ; // Объект, к которому выполняется привязка 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).

Функция

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

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

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

function sayHello(name)  alert("Здравствуйте, " + name); > 

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

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

sayHello("Иван"); // "Здравствуйте, Иван" sayHello("Светлана"); // "Здравствуйте, Светлана" 

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

Также в JavaScript есть анонимные (или безымянные) функции. Такие функции не имеют своего имени.

function()  alert('привет'); // встроенная функция, показывающая диалоговое окно с сообщением > 

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

let myFunc = function()  alert("привет"); >; myFunc(); 

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

setTimeout(func, delay); 

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

setTimeout(function()  alert("привет"); >, 5000); 

Такая функция, которая передается в качестве аргумента другой функции, еще называется функцией обратного вызова (callback function). Функция обратного вызова даёт возможность функциям выполнять код, который был передан им в аргументах при их вызове. Например:

function sayHello(name)  alert("Здравствуйте, " + name); > function processUserInput(callback)  var name = prompt("Введите своё имя."); callback(name); > processUserInput(sayHello); 

В этом примере, при вызове функции processUserInput , ей передаётся в качестве аргумента функция sayHello . После того, как пользователь введёт своё имя name , эта функция обратного вызова будет вызвана с именем пользователя в качестве аргумента.

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

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

 name: sayHello, length: 1, // другие свойства. > 

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

function sayHello(name)  alert("Здравствуйте, " + name); > sayHello.newProperty = "Новое свойство"; sayHello.newProperty; 

Или же можно наоборот, добавить функцию в свойство другого объекта:

let car =  color: "red", wheels: 4, engine:  cylinders: 4, size: 2.2 >, drive: function()  alert("Внимание, я еду!"); > >; 

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

В JavaScript есть набор уже встроенных функций, например:

let myNumber = Math.random(); 

Здесь Math является встроенным объектом, хранящим в своих свойствах и методах различные математические константы и функции. А его метод random() генерирует и возвращает случайное число от 0 до 1. Также, в самом браузере есть встроенные функции, например alert и prompt , которые использовались ранее. Технически эти встроенные функции являются методами внутреннего объекта браузера window и полная запись их вызова выглядит так:

window.alert(message); let result = window.prompt(message, default); 

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

Все функции в JavaScript возвращают значение. Им является то, что указано после ключевого слова return

function square(number)  return number * number; > let result = square(2); // 4 

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

function sayHello(name)  alert("Здравствуйте, " + name); // нет явно указанного возвращаемого значения через return > let result = sayHello("Мария"); // сначала отобразится сообщение, а затем переменной result присвоится значение undefined 

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

function sayHello(name)  alert("Здравствуйте, " + name); return; alert("До свидания, " + name); // не выполнится, т. к. команда return завершит выполнение функции раньше, чем выполнится эта строка > let result = sayHello("Мария"); // сначала отобразится сообщение "Здравствуйте, Мария", а затем переменной result присвоится значение undefined, второе сообщение не отобразится 

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

Дата изменения: February 26, 2023

Поделиться

Обнаружили ошибку или хотите добавить что-то своё в документацию? Отредактируйте эту страницу на GitHub!

Функция

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

Время чтения: 6 мин

Открыть/закрыть навигацию по статье

  1. Кратко
  2. Как пишется
  3. Как понять
    1. Имя функции
    2. Параметры
    3. Функция и переменные
    4. Стрелочные функции
    5. Рекурсивные функции
    6. Контекст функции
    1. Дока Дог советует
    2. Алексей Никитченко советует
    1. Каков типичный случай использования анонимных функций?
    2. В чём плюс использования стрелочных функций для методов в конструкторе?
    3. Пусть у нас объявлена функция function Animal () < >.
    4. Почему JavaScript функции являются объектами первого класса (First-class Objects)?
    5. Что такое IIFE?

    Контрибьюторы:

    Обновлено 24 августа 2022

    Кратко

    Скопировать ссылку "Кратко" Скопировано

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

    Как пишется

    Скопировать ссылку "Как пишется" Скопировано

    Первый способ — просто объявить функцию в коде (по-английски Function Declaration):

     function hello(name)  alert(`Привет $ ��`)> function hello(name)  alert(`Привет $name> ��`) >      

    Второй — создать функциональное выражение (Function Expression). Это похоже на первый способ, но здесь функция становится значением переменной:

     const hello = function(name)  alert(`Привет $ ��`)> const hello = function(name)  alert(`Привет $name> ��`) >      

    Способы написать функцию из примеров выше не одно и тоже (хотя и выглядят почти одинаково ��). Основное отличие в том, что если мы использовали Function Declaration, то JavaScript перенесёт функции вверх текущей области видимости. Это называется «поднятие» (или hoisting).

    На практике это означает, что мы можем использовать её до своего же объявления. Пишем — заработай, и где-то потом объясняем как. Магия!

     hello('Иван') function hello(name)  alert(`Привет $ ��`)> hello('Иван') function hello(name)  alert(`Привет $name> ��`) >      

    Использование Function Expression вызовет ошибку:

     hello('Иван') const hello = function (name)  alert(`Привет $ ��`)> // hello is not a function hello('Иван') const hello = function (name)  alert(`Привет $name> ��`) > // hello is not a function      

    Как понять

    Скопировать ссылку "Как понять" Скопировано

    Объявление функции расшифровывается так:

    • В начале идёт ключевое слово function , чтобы заявить о наших намерениях объявить функцию;
    • Затем имя функции, чтобы можно было отличить одну функцию от другой (у нас лаконичное hello , но бывает лаконичное ничего. );
    • В круглых скобках мы указываем параметры (можно и без), которые передадим внутрь;
    • Наконец, тело функции — это код в фигурных скобках, который выполняется при её вызове.

    Вызвать функцию ещё проще. Создадим новую и назовём её make Shawarma :

     function makeShawarma(meat)  alert(`Ваша шаурма с $ готова ��`)> function makeShawarma(meat)  alert(`Ваша шаурма с $meat> готова ��`) >      

    Для вызова сперва пишем имя функции, а затем в круглых скобках указываем аргумент (или аргументы), например, слово курочкой . Мы объявляем: запусти make Shawarma с курочкой внутри.

     makeShawarma('курочкой') makeShawarma('курочкой')      

    Имя функции

    Скопировать ссылку "Имя функции" Скопировано

    Функцию стоит называть так, чтобы название объясняло её действие. Так другим людям понятнее читать код, а вам не придётся вспоминать или разбираться, что такое таинственный function Igor Misha Pasha123321 ( ) ��. Это же правило касается и переменных: передаём имя — называем name .

    Обычно имя функции пишут стилем camelCase и используют в начале глагол. Например create Bear Counter , get Bear Calculator , send Bear Police .

    В JavaScript есть два типа функций по признаку имени. В примере ниже функция называется именованной, потому что у неё есть имя.

     function namedFunction() <> function namedFunction() >      

    Противоположность именованным функциям — анонимные. У таких имени нет:

     function() <> function() >      

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

     function functionA()  function functionB()  throw new Error('Ошибочка!') > functionB()> functionA() // Error: Ошибочка!// at functionB (/index.js:3:11)// at functionA (/index.js:6:3) function functionA()  function functionB()  throw new Error('Ошибочка!') > functionB() > functionA() // Error: Ошибочка! // at functionB (/index.js:3:11) // at functionA (/index.js:6:3)      

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

    Параметры

    Скопировать ссылку "Параметры" Скопировано

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

    Например, функция show Message принимает два параметра под названиями user и message , а потом соединяет их для целого сообщения.

     function showMessage(user, message)  console.log(user + ': ' + message)> function showMessage(user, message)  console.log(user + ': ' + message) >      

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

     showMessage('Маша', 'Привет!')// Маша: Привет! showMessage('Иван', 'Как делишки?')// Иван: Как делишки? showMessage('Маша', 'Привет!') // Маша: Привет! showMessage('Иван', 'Как делишки?') // Иван: Как делишки?      

    Функция и переменные

    Скопировать ссылку "Функция и переменные" Скопировано

    Переменные внутри функции существуют только внутри этой функции — этот эффект называется областью видимости.

     function five()  const numberFive = 5> console.log(numberFive)//numberFive is not defined function five()  const numberFive = 5 > console.log(numberFive) //numberFive is not defined      

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

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

     const numberFour = 4 function five()  const numberFive = numberFour + 1 return numberFive> console.log(numberFour)// 4console.log(five())// 5console.log(numberFive)// numberFive is not defined const numberFour = 4 function five()  const numberFive = numberFour + 1 return numberFive > console.log(numberFour) // 4 console.log(five()) // 5 console.log(numberFive) // numberFive is not defined      

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

    �� В примере выше было ключевое слово «return». Что это такое и для чего нужно — более подробно раскрыто в отдельной статье про return ��

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

    Скопировать ссылку "Стрелочные функции" Скопировано

    Стрелочная функция записывается намного короче, чем обычная. В самой простой записи ключевое слово function и фигурные скобки не требуются.

     const divider = (number) => number / 2 const divider = (number) => number / 2      

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

     const divider = (numerator, denominator) =>  const result = numerator / denominator return result> const divider = (numerator, denominator) =>  const result = numerator / denominator return result >      

    А ещё у стрелочных функций нет контекста выполнения, но о нём чуть ниже.

    Рекурсивные функции

    Скопировать ссылку "Рекурсивные функции" Скопировано

    Внутри функции можно вызывать её саму — это пример рекурсивной функции.

     function fac(n)  if (n < 2)  return 1 > else  return n * fac(n - 1) >> console.log(fac(3))// 6 function fac(n)  if (n  2)  return 1 > else  return n * fac(n - 1) > > console.log(fac(3)) // 6      

    Если разложить пример, то получится следующая цепочка:

    • fac ( 3 ) это 3 * fac ( 2 ) ;
    • fac ( 2 ) это 2 * fac ( 1 ) ;
    • fac ( 1 ) это 1.

    Получается, что fac ( 3 ) это 3 * 2 * 1, то есть 6. Такой подход часто применяется в математических операциях, но не ограничивается ими.

    Контекст функции

    Скопировать ссылку "Контекст функции" Скопировано

    У кода в момент выполнения есть «окружение». Это функция, которая сейчас отрабатывает, это содержащиеся в ней переменные, это глобальные переменные. Всё это и есть контекст.

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

    На практике

    Скопировать ссылку "На практике" Скопировано

    Дока Дог советует

    Скопировать ссылку "Дока Дог советует" Скопировано

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

    �� Давайте функциям имена, чтобы отладку проводить было проще.

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

     someElement.addEventListener('click', function ()  throw new Error('Error when clicked!')>) someElement.addEventListener('click', function ()  throw new Error('Error when clicked!') >)      

    В отличие от именованной:

     someElement.addEventListener('click', function someElementClickHandler()  throw new Error('Error when clicked!')>) someElement.addEventListener('click', function someElementClickHandler()  throw new Error('Error when clicked!') >)      

    �� У стрелочных функций можно использовать неявный (implicit) return :

     const arrowFunc1 = () =>  return 42> const arrowFunc2 = () => 42 arrowFunc1() === arrowFunc2()// true// Обе функции возвращают 42 const arrowFunc1 = () =>  return 42 > const arrowFunc2 = () => 42 arrowFunc1() === arrowFunc2() // true // Обе функции возвращают 42      

    Также можно возвращать любые структуры и типы данных:

     const arrowFunc3 = () => 'строка'const arrowFunc4 = () => ['массив', 'из', 'строк'] const arrowFunc3 = () => 'строка' const arrowFunc4 = () => ['массив', 'из', 'строк']      

    Чтобы вернуть объект, его необходимо обернуть в скобки. Только так JS поймёт, что мы не открываем тело функции, а возвращаем результат:

     const arrowFunc5 = () => (< cat: 'Барс' >) console.log(arrowFunc5())// const arrowFunc5 = () => ( cat: 'Барс' >) console.log(arrowFunc5()) //     

    + Развернуть

    Алексей Никитченко советует

    Скопировать ссылку "Алексей Никитченко советует" Скопировано

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

     [1, 2, 3, 4, 5].map(function (num)  return num * 2>) [1, 2, 3, 4, 5].map(function (num)  return num * 2 >)      

    Или в вызов другой функции:

     function makeCouple(recipe)  const green = '��' const red = '��' return recipe(green, red)> const result = makeCouple(function(one, two) < return one + two >)console.log(result)//���� function makeCouple(recipe)  const green = '��' const red = '��' return recipe(green, red) > const result = makeCouple(function(one, two)  return one + two >) console.log(result) //����      

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

    Это не самая простая концепция, она подробно разбирается в статье «Функция как тип данных».

    Функции в JavaScript и классический способ их создания

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

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

    Повторяющие блоки кода, которые можно вынести в JavaScript функцию

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

    let a = 5; let b = 7; function sum(a, b) { sum = a + b; console.log(sum); } sum(a, b); // 12 a = 10; b = 4; sum(a, b); // 14 

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

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

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

    • Function Declaration ;
    • Function Expression ;
    • Arrow Function .

    В этой статье разберём первый классический способ, который называется Function Declaration .

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

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

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

    1. Объявление функции. Написание функции посредством Function Declaration начинается с ключевого слова function . После чего указывается имя , круглые скобки , внутрь которых при необходимости помещаются параметры, и тело , заключённое в фигурные скобки. Имя функции ещё очень часто называют названием. В теле пишутся те действия, которые вы хотите выполнить с помощью этой функции.

    // nameFn – имя функции, params – параметры function nameFn (params) { // тело функции }
    // объявляем функцию someName function someName() { console.log('Вы вызвали функцию someName!'); } // function – ключевое слово, которое означает, что мы создаём функцию // someName – имя функции // () – круглые скобки, внутри которых при необходимости описываются параметры // { . } – тело функции

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

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

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

    // объявляем функцию с двумя параметрами function fullname(firstname, lastname) { console.log(`${firstname} ${lastname}`); }

    Параметры ведут себя как переменные и в теле функции мы имеем доступ к ним. Значения этих переменных (в данном случае firstname и lastname ) определяются в момент вызова функции. Обратиться к ним вне функции нельзя.

    Если параметры не нужны, то круглые скобки всё равно указываются.

    2. Вызов функции. Объявленная функция сама по себе не выполняется. Запуск функции выполняется посредством её вызова.

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

    // объявляем функцию someName function someName() { console.log('Вы вызвали функцию someName!'); } // вызываем функцию someName someName();

    Параметры и аргументы

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

    Аргументы – это значения, которые мы передаём в функцию в момент её вызова.

    // userFirstName и userLastName – параметры (userFirstName будет иметь значение первого аргумента, а userLastName соответственно второго в момент вызова этой функции) function sayWelcome (userFirstName, userLastName) { console.log(`Добро пожаловать, ${userLastName} ${userFirstName}`); } // 'Иван' и 'Иванов' – аргументы sayWelcome('Иван', 'Иванов'); // Добро пожаловать, Иванов Иван // 'Петр' и 'Петров' – аргументы sayWelcome('Петр', 'Петров'); // Добро пожаловать, Петров Петр

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

    function sayWelcome (userFirstName, userLastName) { console.log( `Добро пожаловать, ${userLastName} ${userFirstName} `); } // с одним аргументом sayWelcome('Иван'); // Добро пожаловать, undefined Иван // без передачи аргументов sayWelcome(); // Добро пожаловать, undefined undefined

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

    let a = 7; let b = 5; function sum (a, b) { a *= 2; // 14 console.log(a + b); } sum(a, b); // 19 console.log(a); // 7

    Передача значения по ссылке

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

    // объявим переменную someUser и присвоим ей объект, состоящий из двух свойств const someUser = { firstname: 'Петр', lastname: 'Петров' } // объявим функцию changeUserName function changeUserName(user) { // изменим значение свойства firstname на новое user.firstname = 'Александр'; } // вызовем функцию changeUserName changeUserName(someUser); // выводим значение свойства firstname в консоль console.log(someUser.firstname); // Александр

    В этом примере переменные someUser и user ссылаются на один и тот же объект в памяти. И когда мы изменяем объект внутри функции, то someUser тоже изменится.

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

    Чтобы избежать изменение внешнего объекта, который мы передаем в функцию через аргумент, необходимо создать копию этого объекта, например, посредством Object.assign:

    const someUser = { firstname: 'Петр', lastname: 'Петров' } function changeUserName(user) { // создадим копию объекта user const copyUser = Object.assign({}, user); // изменим значение свойства firstname на новое copyUser.firstname = 'Александр'; // вернём копию объекта в качестве результата return copyUser; } // вызовем функцию и сохраним результат вызова функции в переменную updatedUser const updatedUser = changeUserName(someUser); // выводим значение свойства firstname в консоль для объекта someUser console.log(someUser.firstname); // Петр // выводим значение свойства firstname в консоль для объекта updatedUser console.log(updatedUser.firstname); // Александр 

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

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

    Локальные и внешние переменные

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

    let a = 7; // объявление функции sum function sum(a) { // локальная переменная функции let b = 8; console.log(a + b); } // вызов функции sum sum(a); console.log(b); // Error: b is not defined

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

    // внешние переменные let a = 7; let b = 3; function sum() { // локальная переменная let a = 8; // изменение значения внешней переменной (т.к. b нет внутри функции) b = 4; console.log(a + b); } sum(); // 12

    Работа с аргументами через arguments

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

    function myFn() { // проверим является ли arguments обычным массивом console.log(Array.isArray(arguments)); // false // количество аргументов console.log(arguments.length); // 0 } myFn(); // false

    Доступ к аргументам через arguments выполняется точно также как к элементам обычного массива, т.е. по порядковому номеру:

    // объявление функции sum function sum() { const num1 = arguments[0]; // получаем значение 1 аргумента const num2 = arguments[1]; // получаем значение 2 аргумента console.log(num1 + num2); } sum(7, 4); // 11

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

    function sum() { let sum = 0; // arguments.length - число аргументов for (let i = 0, length = arguments.length; i < length; i++) { if (typeof arguments[i] === 'number') { sum += arguments[i]; } } console.log(sum); } sum(4, 20, 17, -6); // 35 sum('', 3, -5, 32, null); // 30

    Через цикл for. of этот пример можно записать так:

    function sum() { let sum = 0; for (argument of arguments) { if (typeof argument === 'number') { sum += argument; } } console.log(sum); }

    При необходимости arguments можно преобразовать в обычный массив:

    function names() { // превращаем arguments в полноценный массив const args = Array.from(arguments); console.log(args); } names('Даша', 'Маша', 'Нина'); // ["Даша", "Маша", "Нина"]

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

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

    function fnA(a, b) { const c = 4; function fnB(d) { console.log(a + b + c + d); } fnB(1); } fnA(3, 5); // 13 fnA(4, 7); // 16 // переменная a не доступна за пределами функции fnA console.log(a); // Uncaught ReferenceError: a is not defined

    При этом внутри функции мы имеем доступ к внешним переменных, но только к тем, которых с таким же именем нет в текущей функции:

    const a = 10; function fa(b) { console.log(a + b); } fa(7); // 17

    Колбэк функции

    Колбэк функция (от английского callback function) – это обычная функция, которая просто вызывается внутри другой функции. Такие функции ещё называются функциями обратного вызова. Они очень часто применяются в асинхронном коде.

    Передаётся колбэк функция в другую через аргумент:

    // колбэк функция function cb() { console.log('callback'); } // функция, которая будет принимать на вход колбэк функцию function fnWithCb(cbFn) { console.log('before calling the callback function'); cbFn(); } // вызываем функцию fnWithCb() и передаём ей в качестве аргумента колбэк функцию cb fnWithCb(cb);

    В этом примере имеются две функции:

    • cb – её будем использовать в роли колбэк функции, т.е. вызывать в fnWithCb ;
    • fnWithCb – эта функция, которая содержит параметр cbFn , он будет при её вызове принимать другую функцию (в данном случае cb ).

    Таким образом, функция cb вызывается внутри функции fnWithCb . В неё она передаётся как аргумент. Без вызова fnWithCb она не вызовется, т.к. она вызывается только внутри fnWithCb .

    JavaScript

    // объявим колбэк функцию function printToLog(message) < console.log(message); >// объявим функцию, имеющую 3 параметра function sum(num1, num2, callback) < // вычислим сумму 2 значений и запишем его в result const result = num1 + num2; // вызовем колбэк функцию callback(result); >// вызовем функцию sum sum(5, 11, printToLog);

    Ещё один пример:

    // колбэк функция function setColorBody() { document.body.style.backgroundColor = '#00ff00'; } // функция, которая будет вызывать функцию setColorBody через 3 секунды setTimeout(setColorBody, 3000);

    В этом примере у нас имеется функция setColorBody . В теле она содержит код, который устанавливает цвет фона .

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

    Функцию setTimeout мы нигде не объявляли, т.к. она присутствует в JavaScript по умолчанию. Оня является методом глобальное объекта window в браузере и global в Node.js.

    Обратите внимание, что в setTimeout мы просто передаём функцию setColorBody . Т.е. сами её не вызываем.

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

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

    Функция – это объект

    Функция в JavaScript, как уже было отмечено выше – это определённый тип объектов, которые можно вызывать. А если функция является объектом, то у неё как у любого объекта имеются свойства. Убедиться в этом очень просто. Для этого можно воспользоваться методом console.dir() и передать ему в качестве аргумента функцию.

    Убеждаемся что функция является объектом и у неё есть свойства

    На изображении показана структура функции sum . Используя точечную запись, мы например, можем получить название функции (свойство name ) и количество параметров( length ):

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

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

    function myFunc() {}; console.log(typeof myFunc); // function

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

    function sum(num1, num2, callback) { const result = num1 + num2; if (typeof callback === 'function') { callback(result); } }

    Возврат значения

    Функция всегда возвращает значение, даже если мы не указываем это явно. По умолчанию она возвращает значение undefined .

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

    // expression – выражение, результат которого будет возвращен функцией myFn function myFn() { return expression; }

    Если return не указать, то функция всё равно возвратит значение, в данном случае undefined .

    function sum(a, b) { console.log(a + b); } // вызовем функцию и сохраним её результат в константу result const result = sum(4, 3); // выведем значение переменной result в консоль console.log(result); // undefined

    С использованием инструкции return :

    function sum(a, b) { // вернём в качестве результата a + b return a + b; } // вызовем функцию и сохраним её результат в константу result const result = sum(4, 3); // выведем значение переменной result в консоль console.log(result); // 7

    Инструкции, расположенные после return никогда не выполняются:

    function sum(a, b) { // вернём в качестве результата a + b return a + b; // код, расположенный после return никогда не выполнится console.log('Это сообщение не будет выведено в консоль'); } sum(4, 90);

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

    Функция, которая возвращает функцию

    В качестве результата функции мы можем также возвращать функцию.

    function outer(a) { return function(b) { return a * b; } } // в one будет находиться функция, которую возвращает outer(3) const one = outer(3); // в two будет находиться функция, которую возвращает outer(4) const two = outer(4); // выведем в консоль результат вызова функции one(5) console.log(one(5)); // 15 // выведем в консоль результат вызова функции two(5) console.log(two(5)); // 20

    Вызовы функции outer(3) и outer(4) возвращают одну и туже функцию, но первая запомнила, что a = 3 , а вторая - что a = 4 . Это происходит из-за того, что функции в JavaScript «запоминают» окружение, в котором они были созданы. Этот приём довольно часто применяется на практике. Так как с помощью него мы можем, например, на основе одной функции создать другие, которые нужны.

    В примере, приведённом выше, мы могли также не создавать дополнительные константы one и two . А вызвать сразу после вызова первой функции вторую.

    // выведем в консоль результат вызова функции one(5) console.log(outer(3)(5)); // 15 // выведем в консоль результат вызова функции two(5) console.log(outer(4)(5)); // 20

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

    Функцию, приведённую в коде мы можем также создать и так:

    function outer(a) { function inner(b) { return a * b; } return inner; }

    Кроме этого в качестве результата мы можем также возвратить внешнюю функцию:

    function fa() { return 'Привет!'; } function fb() { return fa; } fb()(); // Привет!

    Рекурсия

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

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

    Например, использование рекурсии для вычисления факториала числа:

    function fact(n) { // условие выхода из рекурсии if (n === 1) { return 1; } // возвращаем вызов функции fact(n - 1) умноженное на n return fact(n - 1) * n; } console.log(fact(5)); // 120

    Пример, в котором используя рекурсию выведем числа от указанного до 10:

    function counter(value) { // условие выхода из рекурсии if (value < 10) { console.log(value); // возвращаем вызов функции counter(value + 1) return counter(value + 1); } } counter(1); // 1, 2, 3, 4, 5, 6, 7, 8, 9 counter(7); // 7, 8, 9

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

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

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

    Например, того чтобы проверить имеет параметр значение или нет, мы можем проверить его значения на undefined . Узнать количества переданных аргументов функции можно через arguments.length . Определить значения параметра можно используя typeof или instanceof .

    Например, создадим функцию bodyBgColor , которая будет иметь 2 режима работы. Если её вызвать без аргументов, то она будет возвращать цвет фона body . А если с текстовым аргументом, то она будет устанавливать цвет фона body .

    // объявление функции bodyBgColor function bodyBgColor(color) { // если параметр color имеет в качестве значения строку, то установим цвет фона body if (typeof color === 'string') { document.body.style.backgroundColor = color; } // вернём в качестве результата текущий цвет фона body return getComputedStyle(document.body).backgroundColor; } // получим текущий цвет body и выведем его в консоль console.log(bodyBgColor()); // установим новый цвет фона body bodyBgColor('green');

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

    function calculateСalories(gender, height) { let result = gender === 'man' ? (height - 100) * 20 : (height - 105) * 19; if (typeof arguments[2] === 'number') { result *= arguments[2]; } return result.toFixed(0); } console.log(`Оптимальное кол-во ккал: ${calculateСalories('man', 185)}`); console.log(`Оптимальное кол-во ккал: ${calculateСalories('woman', 168, 1.2)}`); console.log(`Оптимальное кол-во ккал: ${calculateСalories('woman', 168)}`);

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

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

    function setBgColor(selector, color = 'green') { const el = document.querySelector(selector); el.style.backgroundColor = color; } setBgColor('body');

    При вызове функции с одним аргументом, второму параметру будет автоматически присвоено строка 'green' .

    Работу параметра по умолчанию можно представить так:

    function setBgColor(selector, color) { const el = document.querySelector(selector); color = color === undefined ? 'green' : color; el.style.backgroundColor = color; } setBgColor('body');

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

    const messages = []; function addNewMessage(text, date = new Date()) { messages.push({ text, date }) }; addNewMessage('Как сделать вкусный коктейль в блендере?'); addNewMessage('Какое мороженое лучше для коктейля?'); console.log(messages);

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

    Остаточные параметры

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

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

    // . nums – остаточные параметры function calc(action, . nums) { const initialValue = action === '*' ? 1 : 0; return nums.reduce((result, current) => { return action === '+' ? result + current : action === '*' ? result * current : 0; }, initialValue) } console.log(calc('+', 3, 4, 21, -4)); // 24 console.log(calc('*', 1, 4, 3)); // 12

    В описании параметров . nums должен всегда быть последним. Если что-то указать после него, то это вызовет ошибку:

     function calc(action, . nums, cb) { // . } calc(); // Uncaught SyntaxError: Rest parameter must be last formal parameter

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

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

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

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

    JavaScript - Вызов функции alert

    Функция в 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 не указать возвращаемое значение.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *