☕ Что в коробке? Как работают функции в JavaScript
Знакомимся с фундаментальным строительным блоком любого приложения на JavaScript — функцией.
Что такое функция
Функция — это блок программы, который выполняет определенное действие, например, возводит в степень или складывает значения.
Представьте, что функция — это коробка, и мы не знаем, что внутри нее. Мы только знаем, что она может делать. И когда нам надо совершить какое-либо действие, мы помещаем значения в эту коробку и она выполняет всю работу.
Результат действия функции можно применить в любом месте программы.
Как объявить функцию
Функция объявляется с помощью команды function
. После чего мы именуем функцию и в скобках записываем ее параметры.
Синтаксис такой:
function имя(параметры) { тело функции (любые команды) };
Например, функция, которая вызывает предупреждение:
function showMessage() { alert( 'Предупреждение!' ); };
Как вызвать функцию
Функцию вызывают по имени. Например, чтобы вызывать функцию из нашего примера, нужно после функции написать showAlert();
Параметры и аргументы
Аргументы
Функции можно задать сколько угодно параметров, а потом передать им любые значения. Функция сама поймет, что необходимо сделать с этими значениями.
Например:
function showMessage(from, text) { // параметра: from, text alert(from + ', ' + text); }; showMessage('Привет', 'мне нравится proglib'); // Привет, Мне нравится proglib
В примере мы используем два параметра: from
и text
. Затем в теле функции соединяем from + ', ' + text
. А снаружи функции присваиваем им аргументы и выводим на экран.
Передачи одной функции в другую
В функцию можно передать значение другой функции. Например:
function getDomNodesBySelector(selector) { return Array.from(document.querySelectorAll(selector)); }; document.querySelector('.total__button').addEventListener('click', applyDiscount); let numDiscount = 15; function applyDiscount() { let items = getDomNodesBySelector('.price-value'); items.forEach(function(item){ item.innerText = item.innerText - (item.innerText*numDiscount/100); }); };
В примере задано две функции:
getDomNodesBySelector
— преобразует найденные селекторы на веб странице в массив.applyDiscount
— считает какую-то величину и берет данные для этого из функцииgetDomNodesBySelector
.
Колбэки
Строки кода в языке JavaScript выполняются по очереди. Например:
function one(){ console.log('один'); } function two(){ console.log('два'); } one();//один two();//два
Но бывают такие случаи, когда нам необходимо отсрочить функцию one()
, чтобы первой выполнилась two()
. Для этого можно использовать setTimeout
.
Например:
function one(){ setTimeout( function(){ console.log(1); }, 500 ); console.log('один'); }// функция выполнится через 500 миллисекунд function two(){ console.log('два'); } first();//два second();//один
Вызов функции с отсрочкой называется колбэк (callback
).
Колбэк передают в виде параметра. Например:
function myHomework(subject, callback) { alert(`Starting my ${subject} homework.`); callback(); } function myHomeworkFinished(){ alert('Finished my homework'); } myHomework('math', myHomeworkFinished);
Функция myHomework
имеет два параметра subject
и callback
.
Затем мы вызываем параметр subject
, а параметр callback
вызовем функцией myHomeworkFinished
.
Когда код выполнится, появятся два предупреждения: Starting my math homework
и Finished my homework
.
Локальные переменные
Локальные переменные видны только внутри тела функции. За пределами функции эти переменные уже не работают.
Например:
function showMessage() { let message = "Я локальная переменная"; // локальная переменная alert( message ); } showMessage(); // Я локальная переменная alert( message ); // <-- будет ошибка, так как переменная видна только внутри функции
В примере мы попытались вывести значение переменной message
двумя способами: внутри функции путем вызова самой функции и путем вызова самой переменной.
В первом случае — получаем результат работы функции.
Во втором случае — получаем ошибку, потому что переменную видно только внутри функции.
Внешние переменные
Давайте возьмем пример выше. Оставим внутри функции значение переменной message
. А за пределами функции заведем другую переменную и назовем ее message
.
function showMessage() { let message = "Я локальная переменная"; // локальная переменная alert( message ); } let message = "Я внешняя переменная" showMessage(); // Я локальная переменная alert( message ); //Я внешняя переменная
В коде у нас две переменные с одинаковым именем. Но наш сценарий будет считать их разными переменными.
В первом случае переменная будет видна программе только внутри функции showMessage()
, во втором случае переменная будет видна всей программе.
Параметры по умолчанию
Когда мы указали параметр и не присвоили ему аргумент, то его значение будет undefined
.
Например:
function showMessage(from, text) { // параметра: from, text alert(from + ', ' + text); } showMessage('Привет', ); // Привет, undefined
В примере параметру text
мы не передали значение аргумента. Поэтому в результате мы видим аргумент параметра from
и undefined
.
Возврат значения
Вернуть значение функции можно с помощью директивы return
в теле функции. Например, напишем функцию, которая складывает два параметра.
function sum(a, b) { return a + b; } let result = sum(1, 2); alert( result ); // 3
В примере мы говорим функции, что необходимо возвращать сумму значений аргументов с помощью директивы return
.
Необходимо помнить, что после return
выполнение операций в функции прекращается. Поэтому, с помощью return
можно прерывать функции.
Функция, которая возвращает функцию
Функцию из предыдущего примера можно записать так:
const generateSumFinder = () => { const sum = (a, b) => a + b; return sum; }; const sum = generateSumFinder(); sum(1, 5);
Что мы сделали:
- Создали переменную
generateSumFinder
и присвоили ей значение стрелочной функции. Когда мы видим значок=>
, перед нами стрелочная функция. - Внутри функции создали переменную
sum
. Это локальная переменная и видна только внутри функции и присвоили ей значение стрелочной функции, которая складывает аргументыa
иb.
- Вернули переменную
sum
. - За пределами функции создали переменную
sum
. Это внешняя переменная и она не зависит от переменной внутри функции. Этой переменной мы присвоили значение функцииgenerateSumFinder
.
Рекурсия
В рекурсии функция вызывает саму себя. Рекурсия достигается за счет конструкции if…else
. Чтобы применить рекурсию нужно определить базовый и рекурсивный случай. Функция будет вызывать саму себя, пока результат не приведет к базовому случаю. В других случаях будет выполняться рекурсивный случай.
Например:
function countdown (i){ if (i <=1){ return i; } else { return i-1 }; }; alert (countdown(1));
Функция будет вызываться каждый раз, пока значение ее параметра i
больше 1
– это рекурсивный случай. Или вызывается при базовом случае при i<=1
.
Перегрузка функций в JavaScript
У перегруженных функций одинаковые имена, но разные параметры. JavaScript не поддерживает перегрузку.
Например:
function overload(a){ console.log(«Параметр») } function overload(a,b){ console.log(«Два параметра») } overload(1); // Два параметра overload(1,2); // Два параметра
Несмотря на то, что в первой функции один параметр, вывод аргументов этой функции выведет два параметра. Как вы помните, второй ее параметр будет undefined
.
В JavaScript есть способы, как перегрузить функцию. Для этого используют метод arguments.length
.
Например:
function overload () { if (arguments.length === 1) { console.log(«Параметр») } if (arguments.length === 2) { console.log(«Два параметра») } } overload(1); // Один параметр overload(1, 2); // Два параметра
В примере с помощью метода arguments.length
мы узнаем количество параметров в функции и выводим столько параметров, сколько аргументов мы задаем.
Выбор имени функции
Чтобы выбрать имя функции, необходимо следовать правилам:
Использовать слова на английском языке
неправильно | правильно |
pokazatSoobsheniye | showMessage |
Использовать глаголы, потому что функция – это действие
неправильно | правильно |
Message (сообщение) | showMessage (показать сообщение) |
Комментарии в функции
Комментарии нужны, чтобы кто-то кроме вас понимал, что происходит в функции.
Например:
function getDomNodesBySelector(selector) { return Array.from(document.querySelectorAll(selector)); };// функция возвращает массив, который она возьмет из списка DOM узлов по указанному селектору.
Замыкания
Замыкание – это функция, которая запоминает свои внешние переменные и может получить к ним доступ. В JavaScript все функции являются замыканиями. Замыкания позволяют функции работать с внешними переменными, даже если они изменились.
Например:
let name = "Nikolay"; function sayHi() { alert("Hi, " + name); } name = "Irina"; sayHi();//Hi, Irina
В примере функция sayHi()
будет оперировать со вторым значением переменной name
. Таким образом, функция замыкает свое действие на известной переменной, где бы не задали ее значение.
Приведем еще один пример:
function makeWorker() { let name = "Nikolay"; return function() { alert(name); }; } let name = "Irina"; // create a function let work = makeWorker(); // call it work(); //Nikolay
В примере функция makeWorker()
замыкается на внутренней переменной name = "Nikolay"
. Поэтому при инициализации переменных, следует обращать внимание, какая функция будет ими пользоваться и на какой из них будет замыкаться.
Стрелочные функции
Функцию можно задать не только с помощью слова function
. Есть способ короче, для этого используют значок =>
.
Например:
let sum = (a, b) => a + b;
Если параметр в функции один, то скобки можно не писать.
Например:
let double = n => n * 2; alert(double(3))//6
Если параметров нет, то пишут круглые скобки.
Например:
let sayHi = () => alert("Hello!"); sayHi();//Hello!
Лексика this
В стрелочных функциях нет лексики this.
Если происходит обращение к this
, его значение берется снаружи.
Например:
let object = { title: "our object", students: ["Nikolay", "Irina", "Roma"], showList() { this.students.forEach( student => alert(this.title + ': ' + student) ); } }; object.showList();
Функции используются, чтобы они выполняли любые действия. Функции позволяют разбить код на блоки, исходя из логики программы. Чтобы овладеть написанием функций, необходимо понимать принципы их работы:
- видимость переменных;
- параметры и аргументы;
- стрелочные функции;
- лексика this;
- замыкания;
- рекурсия;
- колбэки.