Энциклопедия мобильной связи

JavaScript функции. Выразительный JavaScript: Функции Автоматическая расстановка точек с запятыми

Операторы перехода и обработка исключений

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

Оператор return заставляет интерпретатор перейти из вызванной функции обратно в точку ее вызова и вернуть значение вызова. Оператор throw возбуждает исключение и предназначен для работы в сочетании с операторами try/catch/finally, которые определяют блок программного кода для обработки исключения. Это достаточно сложная разновидность операторов перехода: при появлении исключения интерпретатор переходит к ближайшему объемлющему обработчику исключений, который может находиться в той же функции или выше, в стеке возвратов вызванной функции.

Подробнее все эти операторы перехода описываются в следующих подразделах.

Метки инструкций

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

идентификатор: инструкция

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

Присвоив имя циклу, его затем можно использовать в инструкциях break и continue, внутри цикла для выхода из него или для перехода в начало цикла, к следующей итерации. Инструкции break и continue являются единственными инструкциями в языке JavaScript, в которых можно указывать метки - о них подробнее рассказывается далее. Ниже приводится пример инструкции while с меткой и инструкции continue, использующей эту метку:

Mainloop: while (token != null) { // Программный код опущен... continue mainloop; // Переход к следующей итерации именованного цикла }

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

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

Оператор break

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

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

Var arr = ["а","б","в","г","д"], result; for (var i = 0; i

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

break имя_метки;

Когда оператор break используется с меткой, она выполняет переход в конец именованной инструкции или прекращение ее выполнения. В случае отсутствия инструкции с указанной меткой попытка использовать такую форму оператора break порождает синтаксическую ошибку. Именованная инструкция не обязана быть циклом или оператором switch. Оператор break с меткой может выполнять «выход» из любой вмещающей ее инструкции. Объемлющая инструкция может даже быть простым блоком инструкций, заключенным в фигурные скобки исключительно с целью пометить его.

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

Оператор break с меткой необходим, только когда требуется прервать выполнение инструкции, не являющейся ближайшим объемлющим циклом или оператором switch.

Оператор continue

Оператор continue схож с оператором break. Однако вместо выхода из цикла оператор continue запускает новую итерацию цикла. Синтаксис оператора continue столь же прост, как и синтаксис оператора break. Оператор continue может также использоваться с меткой.

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

    В цикле while указанное в начале цикла выражение проверяется снова, и если оно равно true, тело цикла выполняется с начала.

    В цикле do/while происходит переход в конец цикла, где перед повторным выполнением цикла снова проверяется условие.

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

    В цикле for/in цикл начинается заново с присвоением указанной переменной имени следующего свойства.

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

Var sum = 0; // Вычислить сумму не четных чисел от 0 - 10 for (var i = 0; i

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

Оператор return

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

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

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

Function myFun(arr) { // Если массив содержит отриц. числа, прервать функцию for (var i = 0; i

Оператор throw

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

В JavaScript исключения возбуждаются в тех случаях, когда возникает ошибка времени выполнения и когда программа явно возбуждает его с помощью оператора throw. Исключения перехватываются с помощью операторов try/catch/finally, которые описываются позже.

Оператор throw имеет следующий синтаксис:

throw выражение;

Результатом выражения может быть значение любого типа. Оператору throw можно передать число, представляющее код ошибки, или строку, содержащую текст сообщения об ошибке. Интерпретатор JavaScript возбуждает исключения, используя экземпляр класса Error одного из его подклассов, и вы также можете использовать подобный подход. Объект Error имеет свойство name , определяющее тип ошибки, и свойство message , содержащее строку, переданную функции-конструктору. Ниже приводится пример функции, которая возбуждает объект Error при вызове с недопустимым аргументом:

// Функция факториала числа function factorial(number) { // Если входной аргумент не является допустимым значением, // возбуждается исключение! if (number 1; i *= number, number--); /* пустое тело цикла */ return i; } console.log("5! = ", factorial(5)); console.log("-3! = ", factorial(-3));

Когда возбуждается исключение, интерпретатор JavaScript немедленно прерывает нормальное выполнение программы и переходит к ближайшему обработчику исключений. В обработчиках исключений используется оператор catch конструкции try/catch/finally, описание которой приведено в следующем разделе.

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

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

Конструкция try/catch/finally

Конструкция try/catch/finally реализует механизм обработки исключений в JavaScript. Оператор try в этой конструкции просто определяет блок кода, в котором обрабатываются исключения. За блоком try следует оператор catch с блоком инструкций, вызываемых, если где-либо в блоке try возникает исключение. За оператором catch следует блок finally , содержащий программный код, выполняющий заключительные операции, который гарантированно выполняется независимо от того, что происходит в блоке try.

И блок catch, и блок finally не являются обязательными, однако после блока try должен обязательно присутствовать хотя бы один из них. Блоки try, catch и finally начинаются и заканчиваются фигурными скобками. Это обязательная часть синтаксиса, и она не может быть опущена, даже если между ними содержится только одна инструкция.

Следующий фрагмент иллюстрирует синтаксис и назначение конструкции try/catch/finally:

Try { // Обычно этот код без сбоев работает от начала до конца. // Но в какой-то момент в нем может быть сгенерировано исключение // либо непосредственно с помощью оператора throw, либо косвенно - // вызовом метода, генерирующего исключение. } catch (ex) { // Инструкции в этом блоке выполняются тогда и только тогда, когда в блоке try // возникает исключение. Эти инструкции могут использовать локальную переменную ex, // ссылающуюся на объект Error или на другое значение, указанное в операторе throw. // Этот блок может либо некоторым образом обработать исключение, либо // проигнорировать его, делая что то другое, либо заново сгенерировать // исключение с помощью оператора throw. } finally { // Этот блок содержит инструкции, которые выполняются всегда, независимо от того, // что произошло в блоке try. Они выполняются, если блок try завершился: // 1) как обычно, достигнув конца блока // 2) из-за операторов break, continue или return // 3) с исключением, обработанным приведенным в блоке catch выше // 4) с неперехваченным исключением, которое продолжает свое // распространение на более высокие уровни }

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

Далее приводится более реалистичный пример конструкции try/catch. В нем вызываются метод factorial(), определенный в предыдущем примере, и методы prompt() и alert() клиентского JavaScript для организации ввода и вывода:

Try { // Запросить число у пользователя var n = Number(prompt("Введите положительное число", "")); // Вычислить факториал числа, предполагая, // что входные данные корректны var f = factorial(n); // Вывести результат alert(n + "! = " + f); } catch (ex) { // Если данные некорректны, управление будет передано сюда alert(ex); // Сообщить пользователю об ошибке }

Если пользователь введет отрицательное число, высветится предупреждающее сообщение:

Это пример конструкции try/catch без оператора finally. Хотя finally используется не так часто, как catch, тем не менее иногда этот оператор оказывается полезным. Блок finally гарантированно исполняется, если исполнялась хотя бы какая-то часть блока try, независимо от того, каким образом завершилось выполнение программного кода в блоке try. Эта возможность обычно используется для выполнения заключительных операций после выполнения программного кода в продолжении try.

В обычной ситуации управление доходит до конца блока try, а затем переходит к блоку finally, который выполняет необходимые заключительные операции. Если управление вышло из блока try как результат выполнения операторов return, continue или break, перед передачей управления в другое место выполняется блок finally.

Если в блоке try возникает исключение и имеется соответствующий блок catch для его обработки, управление сначала передается в блок catch, а затем - в блок finally. Если отсутствует локальный блок catch, то управление сначала передается в блок finally, а затем переходит на ближайший внешний блок catch, который может обработать исключение.

Если сам блок finally передает управление с помощью операторов return, continue, break или throw или путем вызова метода, генерирующего исключение, незаконченная команда на передачу управления отменяется и выполняется новая. Например, если блок finally сгенерирует исключение, это исключение заменит любое ранее сгенерированное исключение.

Функции являются одним из наиболее важных строительных блоков кода в JavaScript.

Функции состоят из набора команд и обычно выполняют какую-то одну определенную задачу (например суммирование чисел, вычисление корня и т.д.).

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

Объявление функций

1. Синтаксис:

//Объявление функции function имяФункции(пер1, пер2){ Код функции } //Вызов функции имяФункции(пер1,пер2);

2. Синтаксис:

//Объявление функции var имяфункции=function(пер1, пер2){Код функции} //Вызов функции имяфункции(пер1,пер2);

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

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

Обратите внимание: даже если в функцию не передаются переменные не забывайте вставлять круглые скобки "()" после имени функции.

Обратите внимание: имена функций в JavaScript чувствительны к регистру.

Пример JavaScript функции

Функция messageWrite() в примере ниже будет выполнена только после нажатия на кнопку.

Обратите внимание: в этом примере используется событие onclick. События JavaScript будут подробно рассмотрены далее в данном учебнике.

// Функция выводит текст на страницу function messageWrite() { document.write("Данный текст был выведен на страницу с помощью JavaScript!"); }

Передача функциям переменных

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

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

/* Зададим функцию, которая прибавляет к переданной переменной 10 и выводит результат на страницу */ function plus(a){ a=a+10; document.write("Вывод функции: " + a+"
"); } var a=25; document.write("Значение переменной до вызова функции: "+a+"
"); // Вызовем функцию передав ей в качестве аргумента переменную a plus(a); document.write("Значение переменной после вызова функции: "+a+"
");

Быстрый просмотр

Чтобы обращаться к глобальной переменной из функции, а не ее копии используйте window.имя_переменной .

Function plus(a){ window.a=a+10; } var a=25; document.write("Значение переменной до вызова функции: "+a+"
"); plus(a); document.write("Значение переменной после вызова функции: "+a+"
");

Быстрый просмотр

Команда return

С помощью команды return Вы можете возвращать из функций значения.

//Функция sum возвращает сумму переданных в нее переменных function sum(v1,v2){ return v1+v2; } document.write("5+6=" + sum(5,6) + "
"); document.write("10+4=" + sum(10,4) + "
");

Быстрый просмотр

Встроенные функции

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

К примеру встроенная функция isFinite позволяет проверить является ли переданное значение допустимым числом.

Document.write(isFinite(40)+"
"); document.write(isFinite(-590)+"
"); document.write(isFinite(90.33)+"
"); document.write(isFinite(NaN)+"
"); document.write(isFinite("Это строка")+"
");

Быстрый просмотр

Обратите внимание: полный список встроенных функций JavaScript Вы можете найти в нашем .

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

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

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

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

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

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

//Объявим глобальные переменные var1 и var2 var var1="var1 существует"; var var2; function func1() { //Присвоим var2 значение внутри функции func1 var var2="var2 существует"; } //Из другой функции выведем содержимое переменной var1 и var2 на страницу function func2() { //Выводим содержимое переменной var1 document.write(var1 + "
"); //Выводим содержимое переменной var2 document.write(var2); }

Быстрый просмотр

Обратите внимание: при выводе на экран переменная var2 будет иметь пустое значение, так как func1 оперирует с локальной "версией" переменной var2.

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

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

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

Function arrMap(arr,func){ var res=new Array; for (var i=0;i target) return null; else return find(start + 5, "(" + history + " + 5)") || find(start * 3, "(" + history + " * 3)"); } return find(1, "1"); } console.log(findSolution(24)); // → (((1 * 3) + 5) * 3)

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

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

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

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

Find(1, "1") find(6, "(1 + 5)") find(11, "((1 + 5) + 5)") find(16, "(((1 + 5) + 5) + 5)") too big find(33, "(((1 + 5) + 5) * 3)") too big find(18, "((1 + 5) * 3)") too big find(3, "(1 * 3)") find(8, "((1 * 3) + 5)") find(13, "(((1 * 3) + 5) + 5)") found!

Отступ показывает глубину стека вызовов. В первый раз функция find вызывает сама себя дважды, чтобы проверить решения, начинающиеся с (1 + 5) и (1 * 3). Первый вызов ищет решение, начинающееся с (1 + 5), и при помощи рекурсии проверяет все решения, выдающие число, меньшее или равное требуемому. Не находит, и возвращает null. Тогда-то оператор || и переходит к вызову функции, который исследует вариант (1 * 3). Здесь нас ждёт удача, потому что в третьем рекурсивном вызове мы получаем 13. Этот вызов возвращает строку, и каждый из операторов || по пути передаёт эту строку выше, в результате возвращая решение.

Выращиваем функции Существует два более-менее естественных способа ввода функций в программу.

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

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

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

007 Коров 011 Куриц

Очевидно, что нам понадобится функция с двумя аргументами. Начинаем кодить.
// вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens) { var cowString = String(cows); while (cowString.length < 3) cowString = "0" + cowString; console.log(cowString + " Коров"); var chickenString = String(chickens); while (chickenString.length < 3) chickenString = "0" + chickenString; console.log(chickenString + " Куриц"); } printFarmInventory(7, 11);

Если мы добавим к строке.length, мы получим её длину. Получается, что циклы while добавляют нули спереди к числам, пока не получат строчку в 3 символа.

Готово! Но только мы собрались отправить фермеру код (вместе с изрядным чеком, разумеется), он звонит и говорит нам, что у него в хозяйстве появились свиньи, и не могли бы мы добавить в программу вывод количества свиней?

Можно, конечно. Но когда мы начинаем копировать и вставлять код из этих четырёх строчек, мы понимаем, что надо остановиться и подумать. Должен быть способ лучше. Пытаемся улучшить программу:

// выводСДобавлениемНулейИМеткой function printZeroPaddedWithLabel(number, label) { var numberString = String(number); while (numberString.length < 3) numberString = "0" + numberString; console.log(numberString + " " + label); } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { printZeroPaddedWithLabel(cows, "Коров"); printZeroPaddedWithLabel(chickens, "Куриц"); printZeroPaddedWithLabel(pigs, "Свиней"); } printFarmInventory(7, 11, 3);

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

// добавитьНулей function zeroPad(number, width) { var string = String(number); while (string.length < width) string = "0" + string; return string; } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { console.log(zeroPad(cows, 3) + " Коров"); console.log(zeroPad(chickens, 3) + " Куриц"); console.log(zeroPad(pigs, 3) + " Свиней"); } printFarmInventory(7, 16, 3);

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

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

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

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

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

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

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

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

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

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

УпражненияМинимум В предыдущей главе была упомянута функция Math.min, возвращающая самый маленький из аргументов. Теперь мы можем написать такую функцию сами. Напишите функцию min, принимающую два аргумента, и возвращающую минимальный из них.

Console.log(min(0, 10)); // → 0 console.log(min(0, -10)); // → -10

Рекурсия Мы видели, что оператор % (остаток от деления) может использоваться для определения того, чётное ли число (% 2). А вот ещё один способ определения:

Ноль чётный.
Единица нечётная.
У любого числа N чётность такая же, как у N-2.

Напишите рекурсивную функцию isEven согласно этим правилам. Она должна принимать число и возвращать булевское значение.

Потестируйте её на 50 и 75. Попробуйте задать ей -1. Почему она ведёт себя таким образом? Можно ли её как-то исправить?

Test it on 50 and 75. See how it behaves on -1. Why? Can you think of a way to fix this?

Console.log(isEven(50)); // → true console.log(isEven(75)); // → false console.log(isEven(-1)); // → ??

Считаем бобы.

Символ номер N строки можно получить, добавив к ней.charAt(N) (“строчка”.charAt(5)) – схожим образом с получением длины строки при помощи.length. Возвращаемое значение будет строковым, состоящим из одного символа (к примеру, “к”). У первого символа строки позиция 0, что означает, что у последнего символа позиция будет string.length – 1. Другими словами, у строки из двух символов длина 2, а позиции её символов будут 0 и 1.

Напишите функцию countBs, которая принимает строку в качестве аргумента, и возвращает количество символов “B”, содержащихся в строке.

Затем напишите функцию countChar, которая работает примерно как countBs, только принимает второй параметр - символ, который мы будем искать в строке (вместо того, чтобы просто считать количество символов “B”). Для этого переделайте функцию countBs.



Понравилась статья? Поделитесь с друзьями!
Была ли эта статья полезной?
Да
Нет
Спасибо, за Ваш отзыв!
Что-то пошло не так и Ваш голос не был учтен.
Спасибо. Ваше сообщение отправлено
Нашли в тексте ошибку?
Выделите её, нажмите Ctrl + Enter и мы всё исправим!