Для чего служат параметры функции?
Я так понимаю, там объявляются типы переменных. А также ссылки (указатели). А разве типы переменных нельзя объявить в теле функции, оставив параметры пустыми f() ? Объясните пожалуйста назначение параметров функций.
Отслеживать
13.7k 12 12 золотых знаков 43 43 серебряных знака 75 75 бронзовых знаков
задан 9 апр 2017 в 6:25
371 1 1 золотой знак 3 3 серебряных знака 15 15 бронзовых знаков
А вызывать как будете? f() — это что, f(1) или f(«Hello») или f(2,4,5,15) ? Вот есть функция sqrt() — квадратный корень. Как ей объяснить, что нам нужен корень именно из 2, а не 18 или 45?
9 апр 2017 в 6:28
То есть в скобках нет никаких параметров, переменные описаны в теле функции. Такое ведь тоже может быть, по сути.
9 апр 2017 в 6:29
Я пытаюсь с этим разобраться, зачем нужны параметры, по-этому прошу объяснить. чтоб вызывать функцию? Вроди-бы можно это делать по ссылке и по значению. Но также типы тоже указываются в параметрах.
9 апр 2017 в 6:32
Каким образом вы предлагаете использовать функцию, скажем, длины строки strlen , если вы не будете передавать в эту функцию никаких параметров? Длину какой строки она будут вычислять?
9 апр 2017 в 6:33
Но длину строки, и все прочее касательно строки можно задать (определить и инициализировать) в теле функции. А вызов этой функции из функции main невозможен без параметров function() ? Скобки нельзя оставить пустыми? Извините, я новичок.
9 апр 2017 в 6:39
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Параметры функции предназначены для общения функции с «внешним миром», т.е. с кодом, который вызвал эту функцию.
Значения параметров внутри функции — это ни что иное, как значения аргументов функции, предоставленные вызывающим кодом в точке вызова. Таким образом вы передаете информацию (аргументы) снаружи из точки вызова внутрь функции. Когда вы вызываете функцию sqrt с аргументом 25
sqrt(25)
значение 25 передается внутрь функции sqrt через ее единственный параметр. Внутри функция sqrt будет знать, что ее попросили вычислить квадратный корень из 25 , Что она и сделает.
Также параметры функции могут использоваться для возвращения результатов работы функции обратно в вызывающий код.
Переменные, которые объявлены локально внутри функции никакой связи с вызывающим кодом не имеют и использоваться для связи с внешним миром не могут.
Параметры процедур и функций
Область применения: управляемое приложение, мобильное приложение, обычное приложение.
1. При объявлении формальных параметров процедур и функций (далее по тексту: функций) необходимо придерживаться общих правил образования имен переменных. В частности, имена параметров следует образовывать от терминов предметной области таким образом, чтобы из имени параметра было понятно его назначение.
2. Не следует использовать вместо параметров функций другие средства конфигурирования (переменные модулей, реквизиты формы и т.п.)
3. Параметры в функции должны идти в логической последовательности. Рекомендуется располагать параметры по принципу от общего к частному.
Например, неправильно:
Процедура ПересчитатьСуммуДокумента(ИмяПоляСумма, ДокументОбъект, СуммаВключаетНДС = Истина) Процедура ПоменятьЦветПоляФормы(Цвет, ИмяПоля, Форма)
правильно сначала расположить основные параметры ДокументОбъект и Форма :
Процедура ПересчитатьСуммуДокумента(ДокументОбъект, ИмяПоляСумма, СуммаВключаетНДС = Истина) Процедура ПоменятьЦветПоляФормы(Форма, ИмяПоля, Цвет)
4. Необязательные параметры (параметры со значениями по умолчанию) должны располагаться после обязательных параметров (без значений по умолчанию).
Например:
Функция КурсВалютыНаДату(Валюта, Дата = Неопределено) Экспорт
5. Не рекомендуется объявлять в функциях много параметров (нужно ориентироваться на количество не более семи параметров), при этом не должно быть много параметров со значениями по умолчанию (нужно ориентироваться на количество не более трех таких параметров). В противном случае, читаемость вызывающего кода сильно снижается. Например, можно легко ошибиться в количестве запятых при передаче необязательных параметров.
При необходимости передавать в функцию большое число параметров рекомендуется:
- группировать однотипные параметры в один или несколько составных параметров типа Структура . Например, в структуры могут быть объединены параметры, описывающие состав и значения полей некоторого объекта ( ДанныеЗаполнения , ПараметрыПроведения, ДанныеФайла и т.п.);
- либо полностью пересмотреть логику работы функции, например, разделив ее на несколько разных, более простых функций.
// Добавляет новое поле на форму, инициализирует его значениями по умолчанию. Функция ДобавитьПолеФормы(ИмяПоля, Заголовок = Неопределено, ОбработчикПриИзменении = "", ОбработчикНачалоВыбора = "", ШиринаПоля, ЦветФона = Неопределено, ЦветФонаЗаголовка = Неопределено, Родитель = Неопределено, КартинкаШапки = Неопределено, ПутьКДанным = Неопределено, ТолькоПросмотрПоля = Ложь, СвязиПараметровВыбора = Неопределено) … КонецФункции // вызывающий код НовоеПоле = ДобавитьПолеФормы("СтараяЦена", НСтр("ru='Цена'"). 12, ЦветФона, ЦветЗаголовка, НоваяГруппа. Истина); НовоеПоле.ЦветТекста = WebЦвета.Серый;
Правильно пересмотреть логику работы функций, оставив в ней только один ключевой параметр ИмяПоля :
// Добавляет новое поле на форму, инициализирует его значениями по умолчанию. Функция НовоеПолеФормы(ИмяПоля) … КонецФункции // вызывающий код НовоеПоле = НовоеПолеФормы("СтараяЦена"); НовоеПоле.Заголовок = НСтр("ru='Цена'"); НовоеПоле.ЦветФона = ЦветФона; НовоеПоле.ЦветТекста = WebЦвета.Серый; НовоеПоле…. = … …
Другой пример. Неправильно:
// Создает элемент справочника "Номенклатура" Процедура СоздатьЭлементНоменклатуры(Наименование, ТоварУслуга, ЕдиницаИзмерения, ВесНетто, ПроверятьУникальность = Истина) … КонецПроцедуры
Правильно сгруппировать параметры, описывающие значения реквизитов номенклатуры, в структуру ЗначенияРеквизитов :
// Создает элемент справочника "Номенклатура" Процедура СоздатьЭлементНоменклатуры(ЗначенияРеквизитов, ПроверятьУникальность = Истина) … КонецПроцедуры
6. При вызове функций необходимо избегать громоздких конструкций, которые приводят к снижению читаемости кода, увеличивают вероятность ошибок и затрудняют отладку.
В частности:
6.1. Не рекомендуется при передаче параметров в одну функцию применять вложенные вызовы других функций.
Неправильно:
СтруктураВложений.Вставить(ПрисоединенныйФайл.Наименование, Новый Картинка(ПолучитьИзВременногоХранилища(ПрисоединенныеФайлы.ПолучитьДанныеФайла(ПрисоединенныйФайл.Ссылка).СсылкаНаДвоичныеДанныеФайла)));
Правильно разбивать такие вызовы на отдельные операторы с помощью вспомогательных локальных переменных:
АдресФайлаИзображения = ПрисоединенныеФайлы.ПолучитьДанныеФайла(ПрисоединенныйФайл.Ссылка).СсылкаНаДвоичныеДанныеФайла; ДанныеИзображения = Новый Картинка(ПолучитьИзВременногоХранилища(АдресФайлаИзображения)); СтруктураВложений.Вставить(ПрисоединенныйФайл.Наименование, ДанныеИзображения);
В то же время, если код с вложенными вызовами получается компактным (не требует переноса выражений) и легко читаемым, то вложенные вызовы допустимы.
Например:
Предупреждение(НСтр("ru='Для выполнения операции необходимо установить расширение работы с файлами.'")); ПеречитатьСуммуПоКурсу(Сумма, КурсВалютыНаДату(Валюта));
6.2. Также не рекомендуется при вызове функций использовать вложенный конструктор структуры: Новый Структура(. ) . Вложенное объявление структуры допустимо только в тех случаях, когда количество ее свойств небольшое (нужно ориентироваться на количество свойств не более трех).
ЗаполнитьЦены(Объект.Товары, , Новый Структура("Дата, Валюта, Соглашение, ПоляЗаполнения", Объект.Дата, Объект.Валюта, Объект.Соглашение, "Цена, СтавкаНДС, ВидЦены, СрокПоставки"), Новый Структура("ПересчитатьСумму, ПересчитатьСуммуСНДС, ПересчитатьСуммуНДС, ПересчитатьСуммуРучнойСкидки, ОчиститьАвтоматическуюСкидку, ОчиститьСуммуВзаиморасчетов", "КоличествоУпаковок", СтруктураПересчетаСуммы, СтруктураПересчетаСуммы, "КоличествоУпаковок", Неопределено, Неопределено));
ПараметрыЗаполнения = Новый Структура; ПараметрыЗаполнения.Вставить("Дата", Объект.Дата); ПараметрыЗаполнения.Вставить("Валюта", Объект.Валюта); ПараметрыЗаполнения.Вставить("Соглашение", Объект.Соглашение); ПараметрыЗаполнения.Вставить("ПоляЗаполнения", "Цена, СтавкаНДС, ВидЦены, СрокПоставки"); ДействияСИзмененнымиСтроками = Новый Структура; ДействияСИзмененнымиСтроками.Вставить("ПересчитатьСумму","КоличествоУпаковок"); ДействияСИзмененнымиСтроками.Вставить("ПересчитатьСуммуСНДС", ПараметрыПересчетыСуммы); ДействияСИзмененнымиСтроками.Вставить("ПересчитатьСуммуНДС", ПараметрыПересчетыСуммы); ДействияСИзмененнымиСтроками.Вставить("ПересчитатьСуммуРучнойСкидки","КоличествоУпаковок"); ДействияСИзмененнымиСтроками.Вставить("ОчиститьАвтоматическуюСкидку"); ДействияСИзмененнымиСтроками.Вставить("ОчиститьСуммуВзаиморасчетов "); ЗаполнитьЦены(Объект.Товары, ПараметрыЗаполнения, ДействияСИзмененнымиСтроками);
7. При вызове функций не следует пропускать обязательные параметры. В противном случае, в параметр будет передано значение Неопределено , на которое функция может быть не рассчитана. Если же значение Неопределено является допустимым, то нужно или его передавать в функцию явно, или сделать этот параметр необязательным со значением по умолчанию Неопределено .
Например, для вызова процедуры
Процедура ПоменятьЦветПоляФормы(Форма, ИмяПоля, Цвет)
ПоменятьЦветПоляФормы(,"РезультатПроверки", ЦветаСтиля.ПоясняющийОшибкуТекст); // пропущен первый параметр Форма ПоменятьЦветПоляФормы(,,); // пропущены все обязательные параметры
ПоменятьЦветПоляФормы(ЭтотОбъект, "РезультатПроверки", Цвет); // указаны все обязательные параметры
См. также
- Передача параметров по ссылке и по значению при вызове процедур и функций (статья на ИТС)
- Особенности использования структур в качестве параметров процедур и функций
- Использование объектов типа Структура
Параметр (программирование)
Пара́метр в программировании — принятый функцией аргумент. Термин «аргумент» подразумевает, что конкретно и какой конкретной функции было передано, а параметр — в каком качестве функция применила это принятое. Т.е. вызывающий код передает аргумент в параметр, который определен в спецификации функции.
Фактический или формальный
По способу применения различают:
- фактический параметр — аргумент, передаваемый в функцию при ее вызове;
- формальный параметр — аргумент, указываемый при объявлении или определении функции. [1][2]
Пример на языке Си:
// Объявление функции. int a - формальный параметр, имя параметра может отсутствовать. int myfunction(int a); // Определение функции. int b - формальный параметр, имя параметра может не совпадать с указанным при объявлении функции. int myfunction(int b) return 0; > int main() int c=0; myfunction(c); // Вызов функции. c - фактический параметр. return 0; >
Передача параметра
Передача параметра возможна по значению и по ссылке. Иногда также используют выражение «передача параметра по адресу». Ниже приведён пример, иллюстрирующий различия этих способов.
Передача параметра по значению
Передача параметра по значению означает что вызывающая функция копирует в память, доступную вызываемой, (обычно стек) непосредственное значение. Изменение копии переменной, соответственно, оригинал не затрагивает.
Передача параметра по адресу
Если необходимо именно изменить переменную из внешней, по отношению к вызываемой функции, области видимости, можно копировать адрес переменной, подлежащей изменению. Соответственно при вызове функции g(&x) приходится использовать операцию взятия адреса. Эта техническая деталь отвлекает внимание программиста от логики прикладной программы, однако в случаях невозможности передачи по ссылке может оказаться единственным решением.
Можно заметить, что передача параметра по адресу является частным случаем передачи по значению: передаваемым значением является адрес, по которому можно найти другое значение — значение переменной x.
Передача параметра по ссылке
Передача параметра по ссылке означает что копируется не само значение, а адрес исходной переменной (как в случае передачи параметра по адресу), однако синтаксис используется такой, чтобы программисту не приходилось использовать операцию разыменования и он мог иметь дело непосредственно со значением, хранящимся по этому адресу (как в случае передачи параметра по значению).
Передача по ссылке позволяет избежать копирования всей информации, описывающей состояние объекта (а это может быть существенно больше чем sizeof(int)) и является необходимой для конструктора копирования.
Если функция возвращает значение по ссылке (например, в виде «return *this;»), то её вызов можно использовать слева от оператора присваивания (смотри также L-выражение).
В случае если передача по ссылке используется именно как средство увеличения быстродействия, но изменение параметра нежелательно, можно использовать передачу по ссылке константного объекта.
Таким образом можно ожидать, что примерная программа напечатает (если закоментировать ошибочную строку) «0010 022 233 333».
Некоторые языки (или их диалекты) не поддерживают передачу по ссылке, некоторые наоборот — передают параметры исключительно по ссылке, что порождает риск непреднамеренного изменения контекста вызывающей функции.
Пример на языке С++:
#include using namespace std; // для использования cout void f(int x) // передача параметра по значению cout ; x = 1; cout ; > void g(int* x) // передача параметра по адресу cout <*x; *x = 2; cout <*x; > void h(int& x) // передача параметра по ссылке cout ; x = 3; cout ; > void i(const int& x) // передача неизменяемого параметра по ссылке cout ; x = 4; //Ошибка из-за которой код не будет скомпилирован cout ; > int main() int x = 0; cout ; f(x); cout <" "; g(&x); cout <" "; h(x); cout <" "; i(x); cout ; return 0; >
См. также
Литература
- В.В.Фаронов 8.2.2. Параметры // 8.2. Описание подпрограммы // Глава 8. Процедуры и функции // Иллюстрированный самоучитель по Турбо Паскалю.
Ссылки
- ↑The GNU C Programming — Actual parameters and formal parameters (англ.) .
- ↑Определение и вызов функций.
- Найти и оформить в виде сносок ссылки на авторитетные источники, подтверждающие написанное.
- Концепции языков программирования
- Переменная (программирование)
Wikimedia Foundation . 2010 .
- Львовская детская железная дорога
- Апостолический протонотарий
Полезное
Смотреть что такое «Параметр (программирование)» в других словарях:
- Параметр (значения) — Параметр (математика) Параметр (программирование) Параметр (свойство карт ККИ) Параметр (техника) … Википедия
- ПРОГРАММИРОВАНИЕ ТЕОРЕТИЧЕСКОЕ — математическая дисциплина, изучающая математич. абстракции программ, трактуемых как объекты, выраженные на формальном языке, обладающие определенной информационной и логич. структурой и подлежащие исполнению на автоматич. устройствах. П. т.… … Математическая энциклопедия
- ПРОГРАММИРОВАНИЕ ПАРАЛЛЕЛЬНОЕ — раздел программирования, связанный с изучением и разработкой методов и средств для: а) адекватного описания в программах естественного параллелизма моделируемых в ЭВМ и управляемых ЭВМ систем и процессов, б) распараллеливания обработки информации … Математическая энциклопедия
- Аргумент (программирование) — У этого термина существуют и другие значения, см. Аргумент. В программировании: аргумент функции значение (число, указатель и т. д.), передаваемое функции, а также символьное имя (название переменной) в тексте программы,… … Википедия
- Параметрическое программирование — (англ. parametrical programming) У этого термина существуют и другие значения, см. Параметрическое программирование (значения). Параметрическое программирование (Макропрограммирование) это язык программирования ЧПУ. Производители систем… … Википедия
- Обобщённое программирование — (англ. generic programming) парадигма программирования, заключающаяся в таком описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание. В том или ином виде поддерживается разными… … Википедия
- Обобщенное программирование — Обобщённое программирование парадигма программирования, заключающаяся в таком описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание. В том или ином виде поддерживается разными языками… … Википедия
- Процедура (программирование) — Подпрограмма (англ. subprogram) поименованная или иным образом идентифицированная часть компьютерной программы, содержащая описание определённого набора действий. Подпрограмма может быть многократно вызвана из разных частей программы. В языках… … Википедия
- Шаблон (программирование) — Шаблоны (англ. template) средство языка C++, предназначенное для кодирования обобщённых алгоритмов, без привязки к некоторым параметрам (например типам данных, размерам буферов, значениям по умолчанию). В C++ возможно создание шаблонов функций и … Википедия
- Trim (программирование) — Trim или strip часто используемое название для строковой функции, которая удаляет начальные и конечные пробелы. Например, в Python: Это тест .strip() возвращает строку: Это тест Содержание 1 Ва … Википедия
- Обратная связь: Техподдержка, Реклама на сайте
- Путешествия
Экспорт словарей на сайты, сделанные на PHP,
WordPress, MODx.
- Пометить текст и поделитьсяИскать в этом же словареИскать синонимы
- Искать во всех словарях
- Искать в переводах
- Искать в ИнтернетеИскать в этой же категории
Функции
Зачастую нам надо повторять одно и то же действие во многих частях программы.
Например, необходимо красиво вывести сообщение при приветствии посетителя, при выходе посетителя с сайта, ещё где-нибудь.
Чтобы не повторять один и тот же код во многих местах, придуманы функции. Функции являются основными «строительными блоками» программы.
Примеры встроенных функций вы уже видели – это alert(message) , prompt(message, default) и confirm(question) . Но можно создавать и свои.
Объявление функции
Для создания функций мы можем использовать объявление функции.
Пример объявления функции:
function showMessage()
Вначале идёт ключевое слово function , после него имя функции, затем список параметров в круглых скобках через запятую (в вышеприведённом примере он пустой) и, наконец, код функции, также называемый «телом функции», внутри фигурных скобок.
function имя(параметры)
Наша новая функция может быть вызвана по своему имени: showMessage() .
function showMessage() < alert( 'Всем привет!' ); >showMessage(); showMessage();
Вызов showMessage() выполняет код функции. Здесь мы увидим сообщение дважды.
Этот пример явно демонстрирует одно из главных предназначений функций: избавление от дублирования кода.
Если понадобится поменять сообщение или способ его вывода – достаточно изменить его в одном месте: в функции, которая его выводит.
Локальные переменные
Переменные, объявленные внутри функции, видны только внутри этой функции.
function showMessage() < let message = "Привет, я JavaScript!"; // локальная переменная alert( message ); >showMessage(); // Привет, я JavaScript! alert( message ); //
Внешние переменные
У функции есть доступ к внешним переменным, например:
let userName = 'Вася'; function showMessage() < let message = 'Привет, ' + userName; alert(message); >showMessage(); // Привет, Вася
Функция обладает полным доступом к внешним переменным и может изменять их значение.
let userName = 'Вася'; function showMessage() < userName = "Петя"; // (1) изменяем значение внешней переменной let message = 'Привет, ' + userName; alert(message); >alert( userName ); // Вася перед вызовом функции showMessage(); alert( userName ); // Петя, значение внешней переменной было изменено функцией
Внешняя переменная используется, только если внутри функции нет такой локальной.
Если одноимённая переменная объявляется внутри функции, тогда она перекрывает внешнюю. Например, в коде ниже функция использует локальную переменную userName . Внешняя будет проигнорирована:
let userName = 'Вася'; function showMessage() < let userName = "Петя"; // объявляем локальную переменную let message = 'Привет, ' + userName; // Петя alert(message); >// функция создаст и будет использовать свою собственную локальную переменную userName showMessage(); alert( userName ); // Вася, не изменилась, функция не трогала внешнюю переменную
Глобальные переменные
Переменные, объявленные снаружи всех функций, такие как внешняя переменная userName в вышеприведённом коде – называются глобальными.
Глобальные переменные видимы для любой функции (если только их не перекрывают одноимённые локальные переменные).
Желательно сводить использование глобальных переменных к минимуму. В современном коде обычно мало или совсем нет глобальных переменных. Хотя они иногда полезны для хранения важнейших «общепроектовых» данных.
Параметры
Мы можем передать внутрь функции любую информацию, используя параметры.
В нижеприведённом примере функции передаются два параметра: from и text .
function showMessage(from, text) < // параметры: from, text alert(from + ': ' + text); >showMessage('Аня', 'Привет!'); // Аня: Привет! (*) showMessage('Аня', "Как дела?"); // Аня: Как дела? (**)
Когда функция вызывается в строках (*) и (**) , переданные значения копируются в локальные переменные from и text . Затем они используются в теле функции.
Вот ещё один пример: у нас есть переменная from , и мы передаём её функции. Обратите внимание: функция изменяет значение from , но это изменение не видно снаружи. Функция всегда получает только копию значения:
function showMessage(from, text) < from = '*' + from + '*'; // немного украсим "from" alert( from + ': ' + text ); >let from = "Аня"; showMessage(from, "Привет"); // *Аня*: Привет // значение "from" осталось прежним, функция изменила значение локальной переменной alert( from ); // Аня
Значение, передаваемое в качестве параметра функции, также называется аргументом.
- Параметр – это переменная, указанная в круглых скобках в объявлении функции.
- Аргумент – это значение, которое передаётся функции при её вызове.
Мы объявляем функции со списком параметров, затем вызываем их, передавая аргументы.
Рассматривая приведённый выше пример, мы могли бы сказать: "функция showMessage объявляется с двумя параметрами, затем вызывается с двумя аргументами: from и "Привет" ".
Значения по умолчанию
Если при вызове функции аргумент не был указан, то его значением становится undefined .
Например, вышеупомянутая функция showMessage(from, text) может быть вызвана с одним аргументом:
showMessage("Аня");
Это не приведёт к ошибке. Такой вызов выведет "*Аня*: undefined" . В вызове не указан параметр text , поэтому предполагается, что text === undefined .
Если мы хотим задать параметру text значение по умолчанию, мы должны указать его после = :
function showMessage(from, text = "текст не добавлен") < alert( from + ": " + text ); >showMessage("Аня"); // Аня: текст не добавлен
Теперь, если параметр text не указан, его значением будет "текст не добавлен"
В данном случае "текст не добавлен" это строка, но на её месте могло бы быть и более сложное выражение, которое бы вычислялось и присваивалось при отсутствии параметра. Например:
function showMessage(from, text = anotherFunction()) < // anotherFunction() выполнится только если не передан text // результатом будет значение text >
Вычисление параметров по умолчанию
В JavaScript параметры по умолчанию вычисляются каждый раз, когда функция вызывается без соответствующего параметра.
В приведённом выше примере, функция anotherFunction() не будет вызвана вообще, если указан параметр text .
С другой стороны, функция будет независимо вызываться каждый раз, когда text отсутствует.
Использование параметров по умолчанию в ранних версиях JavaScript
Ранние версии JavaScript не поддерживали параметры по умолчанию. Поэтому существуют альтернативные способы, которые могут встречаться в старых скриптах.
Например, явная проверка на undefined :
function showMessage(from, text) < if (text === undefined) < text = 'текст не добавлен'; >alert( from + ": " + text ); >
…Или с помощью оператора || :
function showMessage(from, text) < // Если значение text ложно, тогда присвоить параметру text значение по умолчанию // заметим, что при этом пустая строка text === "" будет также считаться отсутствующим значением text = text || 'текст не добавлен'; . >
Альтернативные параметры по умолчанию
Иногда имеет смысл присваивать значения по умолчанию для параметров не в объявлении функции, а на более позднем этапе.
Во время выполнения функции мы можем проверить, передан ли параметр, сравнив его с undefined :
function showMessage(text) < // . if (text === undefined) < // если параметр отсутствует text = 'пустое сообщение'; >alert(text); > showMessage(); // пустое сообщение
…Или мы можем использовать оператор || :
function showMessage(text) < // если значение text ложно или равняется undefined, тогда присвоить text значение 'пусто' text = text || 'пусто'; . >
Современные движки JavaScript поддерживают оператор нулевого слияния ?? . Его использование будет лучшей практикой, в случае, если большинство ложных значений, таких как 0 , следует расценивать как «нормальные».
function showCount(count) < // если count равен undefined или null, показать "неизвестно" alert(count ?? "неизвестно"); >showCount(0); // 0 showCount(null); // неизвестно showCount(); // неизвестно
Возврат значения
Функция может вернуть результат, который будет передан в вызвавший её код.
Простейшим примером может служить функция сложения двух чисел:
function sum(a, b) < return a + b; >let result = sum(1, 2); alert( result ); // 3
Директива return может находиться в любом месте тела функции. Как только выполнение доходит до этого места, функция останавливается, и значение возвращается в вызвавший её код (присваивается переменной result выше).
Вызовов return может быть несколько, например:
function checkAge(age) < if (age >= 18) < return true; >else < return confirm('А родители разрешили?'); >> let age = prompt('Сколько вам лет?', 18); if ( checkAge(age) ) < alert( 'Доступ получен' ); >else
Возможно использовать return и без значения. Это приведёт к немедленному выходу из функции.
function showMovie(age) < if ( !checkAge(age) ) < return; >alert( "Вам показывается кино" ); // (*) // . >
В коде выше, если checkAge(age) вернёт false , showMovie не выполнит alert .
Результат функции с пустым return или без него – undefined
Если функция не возвращает значения, это всё равно, как если бы она возвращала undefined :
function doNothing() < /* пусто */ >alert( doNothing() === undefined ); // true
Пустой return аналогичен return undefined :
function doNothing() < return; >alert( doNothing() === undefined ); // true
Никогда не добавляйте перевод строки между return и его значением
Для длинного выражения в return может быть заманчиво разместить его на нескольких отдельных строках, например так:
return (some + long + expression + or + whatever * f(a) + f(b))
Код не выполнится, потому что интерпретатор JavaScript подставит точку с запятой после return . Для него это будет выглядеть так:
return; (some + long + expression + or + whatever * f(a) + f(b))
Таким образом, это фактически стало пустым return .
Если мы хотим, чтобы возвращаемое выражение занимало несколько строк, нужно начать его на той же строке, что и return . Или, хотя бы, поставить там открывающую скобку, вот так:
return ( some + long + expression + or + whatever * f(a) + f(b) )
И тогда всё сработает, как задумано.
Выбор имени функции
Функция – это действие. Поэтому имя функции обычно является глаголом. Оно должно быть кратким, точным и описывать действие функции, чтобы программист, который будет читать код, получил верное представление о том, что делает функция.
Как правило, используются глагольные префиксы, обозначающие общий характер действия, после которых следует уточнение. Обычно в командах разработчиков действуют соглашения, касающиеся значений этих префиксов.
Например, функции, начинающиеся с "show" обычно что-то показывают.
Функции, начинающиеся с…
- "get…" – возвращают значение,
- "calc…" – что-то вычисляют,
- "create…" – что-то создают,
- "check…" – что-то проверяют и возвращают логическое значение, и т.д.
Примеры таких имён:
showMessage(..) // показывает сообщение getAge(..) // возвращает возраст (получая его каким-то образом) calcSum(..) // вычисляет сумму и возвращает результат createForm(..) // создаёт форму (и обычно возвращает её) checkPermission(..) // проверяет доступ, возвращая true/false
Благодаря префиксам, при первом взгляде на имя функции становится понятным, что делает её код, и какое значение она может возвращать.
Одна функция – одно действие
Функция должна делать только то, что явно подразумевается её названием. И это должно быть одним действием.
Два независимых действия обычно подразумевают две функции, даже если предполагается, что они будут вызываться вместе (в этом случае мы можем создать третью функцию, которая будет их вызывать).
Несколько примеров, которые нарушают это правило:
- getAge – будет плохим выбором, если функция будет выводить alert с возрастом (должна только возвращать его).
- createForm – будет плохим выбором, если функция будет изменять документ, добавляя форму в него (должна только создавать форму и возвращать её).
- checkPermission – будет плохим выбором, если функция будет отображать сообщение с текстом доступ разрешён/запрещён (должна только выполнять проверку и возвращать её результат).
В этих примерах использовались общепринятые смыслы префиксов. Конечно, вы в команде можете договориться о других значениях, но обычно они мало отличаются от общепринятых. В любом случае вы и ваша команда должны чётко понимать, что значит префикс, что функция с ним может делать, а чего не может.
Сверхкороткие имена функций
Имена функций, которые используются очень часто, иногда делают сверхкороткими.
Например, фреймворк jQuery определяет функцию с помощью $ . В библиотеке Lodash основная функция представлена именем _ .
Это исключения. В основном имена функций должны быть в меру краткими и описательными.
Функции == Комментарии
Функции должны быть короткими и делать только что-то одно. Если это что-то большое, имеет смысл разбить функцию на несколько меньших. Иногда следовать этому правилу непросто, но это определённо хорошее правило.
Небольшие функции не только облегчают тестирование и отладку – само существование таких функций выполняет роль хороших комментариев!
Например, сравним ниже две функции showPrimes(n) . Каждая из них выводит простое число до n .
Первый вариант использует метку nextPrime :
function showPrimes(n) < nextPrime: for (let i = 2; i < n; i++) < for (let j = 2; j < i; j++) < if (i % j == 0) continue nextPrime; >alert( i ); // простое > >
Второй вариант использует дополнительную функцию isPrime(n) для проверки на простое:
function showPrimes(n) < for (let i = 2; i < n; i++) < if (!isPrime(i)) continue; alert(i); // простое >> function isPrime(n) < for (let i = 2; i < n; i++) < if ( n % i == 0) return false; >return true; >
Второй вариант легче для понимания, не правда ли? Вместо куска кода мы видим название действия ( isPrime ). Иногда разработчики называют такой код самодокументируемым.
Таким образом, допустимо создавать функции, даже если мы не планируем повторно использовать их. Такие функции структурируют код и делают его более понятным.
Итого
Объявление функции имеет вид:
function имя(параметры, через, запятую) < /* тело, код функции */ >
- Передаваемые значения копируются в параметры функции и становятся локальными переменными.
- Функции имеют доступ к внешним переменным. Но это работает только изнутри наружу. Код вне функции не имеет доступа к её локальным переменным.
- Функция может возвращать значение. Если этого не происходит, тогда результат равен undefined .
Для того, чтобы сделать код более чистым и понятным, рекомендуется использовать локальные переменные и параметры функций, не пользоваться внешними переменными.
Функция, которая получает параметры, работает с ними и затем возвращает результат, гораздо понятнее функции, вызываемой без параметров, но изменяющей внешние переменные, что чревато побочными эффектами.
- Имя функции должно понятно и чётко отражать, что она делает. Увидев её вызов в коде, вы должны тут же понимать, что она делает, и что возвращает.
- Функция – это действие, поэтому её имя обычно является глаголом.
- Есть много общепринятых префиксов, таких как: create… , show… , get… , check… и т.д. Пользуйтесь ими как подсказками, поясняющими, что делает функция.
Функции являются основными строительными блоками скриптов. Мы рассмотрели лишь основы функций в JavaScript, но уже сейчас можем создавать и использовать их. Это только начало пути. Мы будем неоднократно возвращаться к функциям и изучать их всё более и более глубоко.
Задачи
Обязателен ли "else"?
важность: 4
Следующая функция возвращает true , если параметр age больше 18 .
В ином случае она запрашивает подтверждение через confirm и возвращает его результат:
function checkAge(age) < if (age >18) < return true; >else < // . return confirm('Родители разрешили?'); >>
Будет ли эта функция работать как-то иначе, если убрать else ?
function checkAge(age) < if (age >18) < return true; >// . return confirm('Родители разрешили?'); >
Есть ли хоть одно отличие в поведении этого варианта?
Оба варианта функций работают одинаково, отличий нет.
Перепишите функцию, используя оператор '?' или '||'
важность: 4
Следующая функция возвращает true , если параметр age больше 18 .
В ином случае она задаёт вопрос confirm и возвращает его результат.
function checkAge(age) < if (age >18) < return true; >else < return confirm('Родители разрешили?'); >>
Перепишите функцию, чтобы она делала то же самое, но без if , в одну строку.
Сделайте два варианта функции checkAge :
- Используя оператор ?
- Используя оператор ||
function checkAge(age) < return (age >18) ? true : confirm('Родители разрешили?'); >
Используя оператор || (самый короткий вариант):
function checkAge(age) < return (age >18) || confirm('Родители разрешили?'); >
Обратите внимание, что круглые скобки вокруг age > 18 не обязательны. Они здесь для лучшей читаемости кода.