Найчастіше нам треба повторювати одну й ту саму дію в багатьох частинах програми. Наприклад, необхідно красиво вивести повідомлення при вітанні відвідувача, при виході відвідувача з сайту ще десь. Щоб не повторювати той самий код у багатьох місцях, придумані функції. Функції є основними "будівельними блоками" програми. Приклади вбудованих функцій ви вже бачили - це alert (message), prompt (message, default) та confirm (question). Але можна творити і свої. Для створення функцій ми можемо використовувати оголошення функції. Приклад оголошення функції: Спочатку йде ключове слово function, після нього ім'я функціїпотім список параметрів у круглих дужках через кому (у наведеному вище прикладі він порожній) і, нарешті, код функції, також званий «тілом функції», усередині фігурних дужок. Наша нова функція може бути викликана своїм ім'ям: showMessage() . Виклик showMessage() виконує код функції. Тут ми побачимо повідомлення двічі. Цей приклад явно демонструє одне з головних призначень функцій: позбавлення дублювання коду. Якщо потрібно змінити повідомлення або спосіб його виведення - достатньо змінити його в одному місці: функції, яка його виводить. Змінні, оголошені всередині функції, видно лише всередині цієї функції. Функція має доступ до зовнішніх змінних, наприклад: Функція має повний доступ до зовнішніх змінних і може змінювати їх значення. Зовнішня змінна використовується тільки якщо всередині функції немає такої локальної. Якщо однойменна змінна оголошується всередині функції, вона перекриває зовнішню. Наприклад, у коді нижче функція використовує локальну змінну userName . Зовнішню буде проігноровано: Змінні, оголошені зовні всіх функцій, такі як зовнішня змінна userName у наведеному вище коді – називаються глобальними. Глобальні змінні видимі для будь-якої функції (якщо їх не перекривають однойменні локальні змінні). Бажано зводити використання глобальних змінних до мінімуму. У сучасному коді зазвичай мало чи зовсім немає глобальних змінних. Хоча вони іноді корисні для зберігання найважливіших «загальнопроектових» даних. Ми можемо передати всередину функції будь-яку інформацію за допомогою параметрів. У наведеному нижче прикладі функції передаються два параметри: from і text . Коли функція викликається в рядках (*) і (**) , передані значення копіюються локальні змінні from і text . Потім вони використовують у тілі функції. Ось ще один приклад: у нас є змінна from, і ми передаємо її функції. Зверніть увагу: функція змінює значення from , але ця зміна не видно ззовні. Функція завжди отримує лише копію значення: Значення, що передається як параметр функції, також називається аргументом. Ми оголошуємо функції зі списком параметрів, потім їх викликаємо, передаючи аргументи. Розглядаючи наведений вище приклад, ми могли б сказати: «функція showMessage оголошується з двома параметрами, потім викликається з двома аргументами: від «Привіт»». Якщо за виклику функції аргумент не було вказано, його значенням стає undefined . Наприклад, вищезазначена функція showMessage(from, text) може бути викликана одним аргументом: Це не призведе до помилки. Такий дзвінок виведе "*Аня*: undefined" . У виклику не вказано параметр text, тому передбачається, що text === undefined. Якщо ми хочемо задати параметру text значення за промовчанням, ми повинні вказати його після = : Тепер, якщо параметр text не вказаний, його значення буде "текст не доданий" В даному випадку "текст не доданий" це рядок, але на її місці міг би бути і складніший вираз, який обчислювався і присвоювався за відсутності параметра. Наприклад: У JavaScript параметри за замовчуванням обчислюються щоразу, коли функція викликається без відповідного аргументу. У наведеному прикладі, функція anotherFunction() не буде викликана взагалі, якщо вказаний аргумент text . З іншого боку, функція буде незалежно викликатися кожного разу, коли аргумент відсутня. Ранні версії JavaScript не підтримували стандартні параметри. Тому є альтернативні способи, які можуть зустрічатися в старих скриптах. Наприклад, явна перевірка на undefined : …Або з допомогою оператора || : Іноді має сенс присвоювати значення за умовчанням параметрів над оголошенні функції, але в пізнішому етапі. Під час виконання функції ми можемо перевірити, чи передано параметр, порівнявши його з undefined : …Або ми можемо використовувати оператор || : Сучасні движки JavaScript підтримують оператор нульового злиття ?? . Його використання буде кращою практикою, якщо більшість помилкових значень, таких як 0 , слід розцінювати як «нормальні». Функція може повернути результат, який буде переданий у код, що її викликав. Найпростішим прикладом може бути функція складання двох чисел: Директива return може бути в будь-якому місці тіла функції. Як тільки виконання доходить до цього місця, функція зупиняється, і значення повертається в код, що її викликав (присвоюється змінної result вище). Викликів return може бути кілька, наприклад: Можна використовувати return і без значення. Це призведе до негайного виходу із функції. У коді вище, якщо checkAge(age) поверне false, showMovie не виконає alert. Якщо функція не повертає значення, це все одно, ніби вона повертала undefined : Порожній return аналогічний return undefined : Для довгого вираження в return може бути привабливо розмістити його на декількох окремих рядках, наприклад: Код не виконається, тому що інтерпретатор JavaScript підставить крапку з комою після return. Для нього це виглядатиме так: Таким чином, це фактично стало порожнім return. Якщо ми хочемо, щоб вираз, що повертається, займало кілька рядків, потрібно почати його на тому ж рядку, що і return . Або, хоча б, поставити там дужку, що відкриває, ось так: І тоді все спрацює, як задумано. Функція – це. Тому ім'я функції зазвичай є дієсловом. Воно має бути коротким, точним і описувати дію функції, щоб програміст, який читатиме код, отримав вірне уявлення про те, що робить функція. Як правило, використовуються дієслівні префікси, що позначають загальний характер дії, після яких слідує уточнення. Зазвичай у командах розробників діють угоди щодо значень цих префіксів. Наприклад, функції, що починаються з "show", зазвичай щось показують. Функції, що починаються з… Приклади таких імен: Завдяки префіксам при першому погляді на ім'я функції стає зрозумілим, що робить її код, і яке значення вона може повертати. Функція повинна виконувати лише те, що очевидно мається на увазі її назвою. І це має бути однією дією. Дві незалежні дії зазвичай мають на увазі дві функції, навіть якщо передбачається, що вони будуть викликатися разом (у цьому випадку ми можемо створити третю функцію, яка їх викликатиме). Декілька прикладів, які порушують це правило: У цих прикладах використовувалися загальноприйняті значення префіксів. Звичайно, ви в команді можете домовитися про інші значення, але вони мало відрізняються від загальноприйнятих. У будь-якому випадку ви та ваша команда повинні чітко розуміти, що означає префікс, що функція з ним може виконувати, а чого не може. Імена функцій, що використовуються дуже часто, Іноді роблять надкороткими. Наприклад, фреймворк jQuery визначає функцію за допомогою $. У бібліотеці Lodash основна функція представлена ім'ям _. Це винятки. В основному імена функцій повинні бути в міру короткими та описовими. Функції мають бути короткими і робити лише щось одне. Якщо це щось велике, є сенс розбити функцію на кілька менших. Іноді дотримуватися цього правила непросто, але це безперечно хороше правило. Невеликі функції не лише полегшують тестування та налагодження – саме існування таких функцій виконує роль добрих коментарів! Наприклад, порівняємо нижче дві функції showPrimes(n) . Кожна їх виводить просте число до n . Перший варіант використовує мітку nextPrime : Другий варіант використовує додаткову функцію isPrime(n) для перевірки на просте: Другий варіант легший для розуміння, чи не так? Замість шматка коду ми бачимо назву дії (isPrime). Іноді розробники називають такий код самодокументованим. Таким чином, можна створювати функції, навіть якщо ми не плануємо повторно використовувати їх. Такі функції структурують код і роблять його більш зрозумілим. Оголошення функції має вигляд: Для того, щоб зробити код чистішим та зрозумілішим, рекомендується використовувати локальні змінні та параметри функцій, не користуватися зовнішніми змінними. Функція, яка отримує параметри, працює з ними і потім повертає результат, набагато зрозуміліше функції, що викликається без параметрів, але змінює зовнішні змінні, що загрожує побічними ефектами. Функції є основними будівельними блоками скриптів. Ми розглянули лише основи функцій у JavaScript, але вже зараз можемо створювати та використовувати їх. Наступна функція повертає true , якщо параметр age більше 18 . В іншому випадку вона запитує підтвердження через confirm і повертає його результат: Чи буде ця функція працювати якось інакше, якщо прибрати else? Чи є хоч одна відмінність у поведінці цього варіанту? Обидва варіанти функцій працюють однаково, відмінностей немає. Наступна функція повертає true , якщо параметр age більше 18 . В іншому випадку вона ставить питання confirm і повертає його результат. Перепишіть функцію, щоб вона робила те саме, але без if , в один рядок. Зробіть два варіанти функції checkAge: Використовуючи оператор ||(найкоротший варіант): Зверніть увагу, що круглі дужки навколо age > 18 не є обов'язковими. При написанні коду часто з'являється необхідність використовувати один і той же функціонал у багатьох місцях програми, для зручного вирішення цього завдання використовують функції. Функція - це блок коду, який вирішує певне завдання або повертає значення і може виконуватися багаторазово у різних місцях та з різними вхідними даними. JavaScript вже має вбудовані функції, такі як Math.random() , prompt(message, default) , Date() та багато інших. Тут ми поговоримо про ті, що їх можна створювати самостійно. Роботу з функціями можна поділити на два етапи: створення (оголошення) та виконання (виклик). function – ключове слово, що позначає функцію. showIntention() - ім'я функції, а круглих дужках її параметри. < >- у фігурних дужках – тіло функції. Для того, щоб функція відпрацювала, ми повинні її викликати. Без виклику функції ми не побачимо повідомлення, а для того, щоб виконати дію кілька разів виклик треба лише продублювати. У результаті ми отримуємо таку програму. Далі розберемо особливості та нюанси, які необхідно знати при роботі з функціями JavaScript Параметри функції JavaScript записуються в круглих дужках і передаються як аргументи в тіло програми, як локальні змінні. При викликі showStudentIntention у локальні змінні name і profession копіюються значення імені та професії в першому випадку це "Лера" та "React-розробник". Далі вони використовують у тілі функції - у результаті ми отримуємо “Лера хоче освоїти професію React-разработчик”. Функція не змінює зовнішні змінні, а отримує копії, з якими працює. У цій програмі перше модальне вікно, яке викликається showStudentIntention буде містити інформацію про Костянтина - всередині функції ми оголосили змінні studentname і profession - зовнішні проігноровані. Другий alert буде про ЛеруОскільки тут значення беруться вже із зовнішніх змінних, які ще називаються глобальними. Такі змінні розташовуються зовні всіх функцій – у робочих проектах їх використання намагаються зводити до мінімуму. Область видимості змінних оголошених усередині функції обмежуються цією функцією. У даному прикладі відпрацює лише виклик функції, другий alert не спрацює, а в консолі можна буде побачити помилку. Uncaught ReferenceError: studentName is not defined. Якщо під час виклику функції параметр не вказується, він приймає значення undefined . Це не буде помилкою – функція відпрацює. Однак у багатьох випадках буде корисніше встановити параметр за замовчуванням. Тут це - profession = "програміст" Також параметри за замовчуванням можуть використовувати значення попередніх параметрів, які розташовані ліворуч. Якщо говорити про максимальну кількість аргументів, які може прийняти функція – це 255. Як результат функція може передавати певне значення, для цього використовують директиву return. За замовчуванням функція повертає undefined, у тому числі і при порожньому return. Сама директива може зустрічатися у тілі функції кілька разів. Як виконання коду доходить до першого return програма зупиняється та повертається відповідне значення. Порожній return використовується і для того, щоб просто припинити виконання функції. При довгому записі може виникнути спокуса додати переклад рядка між return та його значенням. Однак робити цього не можна, якщо не укласти значення в круглі дужки. Функції є одними з найважливіших будівельних блоків програми JavaScript. Вони бувають вбудованими, коли функціонал вже закладено у мові та самописними. Самописні функції можуть бути записані за допомогою різного синтаксису: Function Declaration, Function Expression і «стрілочні функції». У цьому уроці ми розглянули лише перший спосіб. Основні моменти роботи з функціями, записаними в стилі Function Declaration: Функції, які ми визначали на попередніх уроках, закінчували свою роботу тим, що друкували на екран якісь дані: Користування від таких функцій не дуже багато, тому що результатом їхньої роботи неможливо скористатися всередині програми. Розглянемо це з прикладу. Візьмемо завдання обробки електронної пошти. Коли користувач реєструється на якомусь сайті, він може ввести email будь-яким способом: Якщо ми збережемо його в такому вигляді в базу даних, то користувач, швидше за все, не зможе увійти на сайт, оскільки вбиватиме адресу без пробілів і використовуючи інший регістр символів. Щоб цього не сталося, email потрібно підготувати до запису до бази, привести його до нижнього регістру та обрізати пробільні символи по краях рядка. Все завдання вирішується в пару рядків: Цей код став можливим лише завдяки поверненню значення. Методи trim() і toLowerCase() нічого не друкують на екран (в консоль), вони повертають результат своєї роботи і тому ми можемо записати їх у константи. Якби вони натомість друкували на екран, ми б не могли присвоїти результат їхньої роботи константі. Як ми не можемо зробити з певною функцією greeting() : Змінимо функцію greeting() таким чином, щоб вона почала повертати дані замість їх друку. Для цього нам потрібно буде виконати повернення замість друку на екран return – особлива інструкція, яка бере вираз, записаний праворуч, і віддає його назовні, коду, який викликав функцію. Як тільки JavaScript натикається на return, виконання функції на цьому завершується. Будь-який код після return не виконується: Навіть якщо функція повертає дані, це обмежує їх у тому, що вона друкує. Крім повернення даних, ми можемо і друкувати: Повертати можна як конкретне значення. Так як return працює з виразами, то праворуч від нього може з'явитися майже все, що завгодно. Тут потрібно керуватися принципами читання коду: Тут ми не повертаємо змінну, завжди повертається значення, яке знаходиться в цій змінній. Нижче наведено приклад з обчисленнями: Запитання на самоперевірку. Що поверне дзвінок, визначений нижче, функції run() ? Реалізуйте функцію sayHurrayThreeTimes() , яка повертає рядок 'hurray! hurray! hurray!'. Якщо ви зайшли в глухий кут, то саме час поставити питання в «Обговореннях». Як правильно поставити запитання: Тести влаштовані таким чином, що вони перевіряють рішення різними способами та на різних даних. Часто рішення працює з одними вхідними даними, але з іншими. Щоб розібратися з цим моментом, вивчіть вкладку «Тести» та уважно подивіться на виведення помилок, у якому є підказки. Це нормально 🙆, у програмуванні одне завдання можна виконати безліччю способів. Якщо ваш код пройшов перевірку, він відповідає умовам завдання. У поодиноких випадках буває, що рішення підігнано під тести, але це видно відразу. Створювати навчальні матеріали, зрозумілі всім без винятку, досить складно. Ми дуже намагаємося, але завжди є що покращувати. Якщо ви зустріли матеріал, який вам незрозумілий, напишіть проблему в «Обговореннях». Ідеально, якщо ви сформулюєте незрозумілі моменти як запитань. Зазвичай нам потрібно кілька днів для внесення поправок. До речі, ви також можете брати участь у покращенні курсів: унизу є посилання на вихідний код уроків, який можна правити прямо з браузера.Функції
Оголошення функції
function showMessage()
function ім'я(параметри)
function showMessage() < alert( 'Всім привіт!'); >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); // Петя, значення зовнішньої змінної було змінено функцієюlet userName = 'Вася'; function showMessage() < let userName = "Петя"; // оголошуємо локальну змінну let message = 'Привіт,' + userName; // Петро alert (message); >// функція створить і використовуватиме свою власну локальну змінну userName showMessage(); alert(userName); // Вася, не змінилася, функція не чіпала зовнішню зміннуПараметри
function showMessage(from, text) < // параметри: from, text alert(from + ': ' + text); >showMessage('Аня', 'Привіт!'); // Аня: Привіт! (*) showMessage('Аня', "Як справи?"); // Аня: Як справи? (**)function showMessage(from, text) < from = '*' + from + '*'; // Дещо прикрасимо "from" alert( from + ': ' + text ); >let from = "Аня"; showMessage(from, "Привіт"); // *Аня*: Привіт // значення "from" залишилося тим самим, функція змінила значення локальної змінної alert(from); // Аня
Значення за замовчуванням
function showMessage(from, text = "текст не доданий") < alert( from + ": " + text ); >showMessage("Аня"); // Аня: текст не доданоfunction showMessage(from, text = anotherFunction()) < // anotherFunction() виконається тільки якщо не передано text // результатом буде значення text >function showMessage(from, text) < if (text === undefined) < text = 'текст не доданий'; >alert( from + ": " + text ); >function showMessage(from, text) < // Якщо значення text хибне, тоді привласнити параметру text значення за замовчуванням // зауважимо, що при цьому порожній рядок text === "" буде також вважатися відсутнім значенням text = text || 'текст не доданий'; . >Альтернативні параметри за замовчуванням
function showMessage(text) < // . if (text === undefined) < // якщо параметр відсутній text = 'порожнє повідомлення'; >alert(text); > showMessage(); // Порожнє повідомленняfunction showMessage(text) < // якщо значення text є хибним або дорівнює undefined, тоді привласнити text значення 'порожньо' text = text || 'порожньо'; . >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); // 3function checkAge(age) < if (age >= 18) < return true; >else < return confirm('А батьки дозволили?'); >> let age = prompt ('Скільки вам років?', 18); if ( checkAge(age) ) < alert( 'Доступ отримано' ); >else
function showMovie(age) < if ( !checkAge(age) ) < return; >alert( "Вам показується кіно"); //(*) //. >function doNothing() < /* порожньо */ >alert( doNothing() === undefined ); // truefunction doNothing() < return; >alert( doNothing() === undefined ); // truereturn (some + long + expression + or + whatever * f(a) + f(b))return; (Some + long + expression + or + whatever * f(a) + f(b))return ( some + long + expression + or + whatever * f(a) + f(b) )Вибір імені функції
showMessage(..) // показує повідомлення getAge(..) // повертає вік (отримуючи його якимось чином) calcSum(..) // обчислює суму та повертає результат createForm(..) // створює форму (і зазвичай повертає її) checkPermission(..) // перевіряє доступ, повертаючи true/false
Функції == Коментарі
функція 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); // Просте>>функція 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; >Разом
function ім'я(параметри, через, кому) < /* тіло, код функції */ >
Завдання
Чи обов'язковий "else"?
function checkAge(age) < if (age >18) < return true; >else < .function checkAge(age) < if (age >18) < return true; >/ .Перепишіть функцію за допомогою оператора '?' або '||'
function checkAge(age) < if (age >18) < return true; >else < return confirm('Батьки дозволили?');function checkAge(age) < return (age >18) ? true : confirm('Батьки дозволили?');function checkAge(age) < return (age >18) || confirm('Батьки дозволили?');Функції JavaScript
Синтаксис
Оголошення функції
function showIntention()
Виклик
function showIntention() < alert( 'Я хочу стати програмістом!'); >showIntention(); showIntention();
Параметри та аргументи
function showStudentIntention(studentName, profession) < alert(studentName + " хоче освоїти професію " + profession); >showStudentIntention("Лера", "React-розробник"); showStudentIntention("Костянтин", "Web-розробник");
let studentName = "Лера"; let profession = "React-розробник" function showStudentIntention(studentName, profession) < studentName = "Костянтин"; profession = "Web-розробник"; alert(studentName + "хоче освоїти професію" + profession); >showStudentIntention(studentName, profession); alert(studentName + "хоче освоїти професію" + profession);
Локальні змінні
function showStudentIntention() < let studentName = "Костянтин"; let profession = "Web-розробник"; alert(studentName + "хоче освоїти професію" + profession); >showStudentIntention() alert(studentName + "вважає професію" + profession + "безперспективною");
Параметри за замовчуванням
function showStudentIntention(studentName, profession = "програміст") < alert(studentName + " хоче освоїти професію " + profession); >showStudentIntention("Лера"); //Лера хоче освоїти професію програміст
function calcScores(studentName, scoresFirstExam, scoresSecondExam, examResults = scoresFirstExam + scoresSecondExam) < alert(studentName + " набрала за іспити " + examResults + " балів"); >calcScores("Лера", 50, 80);
Повернення значення - return
function calcScores(scoresFirstExam, scoresSecondExam, scoresThirdExam) < let examResults = "Результат за три іспити" + (scoresFirstExam + scoresSecondExam + scoresThirdExam); return examResults; >alert(calcScores(50, 50, 80));
function calcScores(scoresFirstExam, scoresSecondExam, scoresThirdExam) < let examResults = scoresFirstExam + scoresSecondExam + scoresThirdExam; if (examResults >= 185) < return "Ви надійшли!"; >else < return "Ви не надійшли!"; >> alert(calcScores(50, 50, 100)); // Ви надійшли! alert(calcScores(50, 50, 50)); // Ви не надійшли!
return a + b + c; // вірно return (a + b + c // вірно) return // інтерпретатор автоматично поставить; після return a + b + c // функція не поверне значення
Разом
JavaScript: Повернення значень
const message = greeting(); console.log(message); // => undefined
// Тепер ми можемо використовувати результат роботи функції const message=greeting(); console.log(message); // => Hello, Hexlet! // І навіть виконати якісь дії над результатом console.log(message.toUpperCase()); // => HELLO, HEXLET!
const greetingWithCodeAfterReturn = () => < return 'Hello, Hexlet!'; console.log('Я ніколи не виконаюся'); >;
const greetingWithReturnAndPrinting = () => < console.log('Я з'явлюся в консолі'); return 'Hello, Hexlet!'; >; // І надрукує текст на екран і поверне значення const message = greetingWithReturnAndPrinting();
// Визначення const run = () => < return 5; return 10; >; // Що буде виведено на екран? console.log(run());
Завдання
const hurray = sayHurrayThreeTimes(); console.log(hurray); // => hurray! hurray! hurray!
Корисне