# Функции, области видимости ## Trivia ### Повторяющиеся действия. Как можно было заметить, компьютеры сильны именно в однотипных задачах, и делают простые задачи очень быстро. Связанные друг с другом однотипные задачи обычно повторяются в циклах (однотипные операции над массивами данных, статистические задачи, отрисовка повторяющихся данных на экране и так далее). Так же есть задачи *по требованию*, которые могут пригодится в любом месте кода. Например: `prompt`, `alert`, `Math.random` и прочие встроенные **функции**, которые являются *подпрограммами*, содержащими в себе программный код, вызываемый для решения определенной задачи. Я думаю понятно, что данные возможности *не являются* возможностями аппаратуры, а воплощены на программном уровне. ### DRY **Don't repeat yourself**. Один из основопологающих принципов разработки. Суть в том, что в процессе программирования вы должны минимизировать повторяющиеся *части кода*, которые делают почти одинаковые задачи; так как копипаста в коде приводит к дублированию отладки, да и вообще некрасиво это :-) ### KISS **Keep It Simple, Stupid**. Решайте задачи самым простым способом. > Отладка кода вдвое сложнее, чем его написание. Так что если вы пишете код настолько умно, насколько можете, то вы по определению недостаточно сообразительны, чтобы его отлаживать. > — *Brian W. Kernighan*. ### DRY > KISS Зачастую эти принципы противоречат друг другу; уменьшение объема кода требует более мощных и сложнее отлаживаемых средств языка; однако в долгосрочной перспективе принцип **DRY** полезней, чем простота кода (**KISS**). ### Пример ```javascript var surname = prompt("Введите фамилию","") if (surname === null || surname === ""){ surname = "Иванов" } var name = prompt("Введите имя","") || "Иван" var fathername = prompt("Введите отчество","") || "Иванович" ``` Это наш пример, который спрашивает у пользователя ФИО ИЛИ берет эти параметры по умолчанию. Как видите, алгоритм ввода ФИО однотипен, и его неплохо было бы выделить в **функцию**. Ко всему прочему, несмотря на эквивалентность алгоритма, `surname` вводится кодом, отличающимся от ввода `name` и `fathername`, что усложняет модификацию и отладку кода. ### Задание Порассуждаем о функциях, какие свойства должны быть у них, что бы они обеспечивали прозрачную работу в комбинации с другим кодом и не имели непредсказуемых побочных эффектов для кода, который их использует. # Ниже спойлер, имейте совесть :-D. Не омрачайте задание подглядыванием ответов. ![СПОЙЛЕР](http://www.websoldier.ru/wp-content/uploads/2015/02/kak-sdelat-spojler-dlya-sajta.jpg) ![СПОЙЛЕР](http://www.websoldier.ru/wp-content/uploads/2015/02/kak-sdelat-spojler-dlya-sajta.jpg) ![СПОЙЛЕР](http://www.websoldier.ru/wp-content/uploads/2015/02/kak-sdelat-spojler-dlya-sajta.jpg) ![СПОЙЛЕР](http://www.websoldier.ru/wp-content/uploads/2015/02/kak-sdelat-spojler-dlya-sajta.jpg) ## Фунцкции **Функция** - подпрограмма, которая принимает определенные параметры при вызове, выполняет определенный код, и возвращает выполнение кода в место вызова, *опционально* (не обязательно) вернув результат работы в место вызова. Свойства **функции**, которые сделали её такой полезной для написания программ: - **Вызов**. Функция может быть вызвана, код функции выполнится в другом месте, после выполнения функции выполнение кода продолжается с места вызова. ```javascript function d() { debugger; } ``` - **Область видимости**. Так как функция не может "знать", из какого контекста она вызывается, то нет возможности знать заранее, совпадают ли имена переменных в функции и вне её. Таким образом вероятны *побочные эффекты* - непредсказуемые изменения переменных во внешнем коде, которые могут вызвать неправильную работу кода в целом; ```javascript var surname = "Петров"; function readSurname() { surname = prompt("Введите фамилию","") if (surname === null || surname === ""){ surname = "Иванов" } } alert(surname); readSurname(); alert(surname); ``` Для решения этой проблемы используется концепция *области видимости* - **правильно** объявленная переменная в функции (через `var`) существует только в функции и создаются каждый раз при вызове функции; внешние же переменные с таким же именем остаются нетронутыми ```javascript var surname = "Петров"; function readSurname() { var surname = prompt("Введите фамилию","") if (surname === null || surname === ""){ surname = "Иванов" } } alert(surname); readSurname(); alert(surname); ``` - **Параметры** Функция должна уметь получить те или иные данные для своего выполнения. Например встроенные функции `confirm`, `prompt`, `alert`. ### Задание Каковы параметры и какой у них смысл в вышеуказанных встроенных функциях? ```javascript var surname = "Петров"; function readSomething() { var surname = prompt("Введите фамилию","") if (surname === null || surname === ""){ surname = "Иванов" } } alert(surname); readSurname(); alert(surname); ``` - **Возвращаемое значение**. Обратите внимание на то, что **функции** можно использовать как переменные в выражениях, однако не всегда это имеет смысл. Более того, функции нельзя присвоит значение, однако можно *прочесть* её значение.