This page was translated from English by the community.Learn more and join the MDN Web Docs community.
Функции — Переиспользуемые блоки кода
Другая важная концепция в кодировании —функции — позволяют хранить фрагмент кода, который выполняет одну задачу внутри определённого блока, а затем вызывать этот код всякий раз, когда вам это нужно, используя одну короткую команду, вместо того, чтобы вводить один и тот же код несколько раз.
В этой статье мы рассмотрим фундаментальные концепции функций, такие как базовый синтаксис, способы вызова и их определения, область действия и параметры.
| Предпосылки: | Начальная компьютерная грамотность, основы HTML и CSS,первые шаги JavaScript. |
|---|---|
| Цель: | Понять фундаментальные основы функций языка JavaScript. |
In this article
Где можно встретить функции?
В JavaScript, вы везде уведите функции. На самом деле, мы пользовались функциями на протяжении всего курса; только мы не говорили об этом слишком часто. Теперь наступило время, чтобы поговорить о функциях более конкретно и разобрать их синтаксис.
В значительном количестве случаев, когда вы пользуетесь структурой JavaScript, в которой есть пара обычных скобок —() — и при этом, это не является структурой типацикл for,while, или do...while цикл, илиif...else конструкция, вы используете функцию.
Встроенные функции браузера
В этом курсе мы использовали функции, встроенные в браузер. Каждый раз, когда мы манипулировали текстовой строкой, например:
var myText = "Я строка";var newString = myText.replace("строка", "сосиска");console.log(newString);// Функция строки replace() принимает строку,// заменяет одну строку на другую, и возвращает// новую строку с заменённым содержимымИли каждый раз, когда мы манипулировали массивом:
var myArray = ["Я", "люблю", "шоколадных", "лягушек"];var madeAString = myArray.join(" ");console.log(madeAString);// Функция join() принимает массив, соединяет// все элементы массива вместе в одну строку,// и возвращает эту новую строкуИли каждый раз, когда мы генерировали случайное число:
var myNumber = Math.random();// Функция random() генерирует случайное число от 0 до 1,// и возвращает это число...мы использовали функции!
Примечание:Вы можете вставить эти строки в консоль вашего браузера, чтобы посмотреть, как работают эти функции.
Фактически, часть кода, который вы вызываете, когда ссылаетесь на встроенную функцию браузера (воображаемое слово для её запуска или выполнения), не может быть написана на JavaScript — многие из этих функций вызывают части фонового кода браузера, который написан в основном на системных языках низкого уровня, таких как C ++, а не на веб-языках, таких как JavaScript.
Имейте в виду, что некоторые встроенные функции браузера не являются частью основного языка JavaScript — некоторые из них являются частью API браузера, которые основываются на языке по умолчанию, чтобы обеспечить ещё большую функциональность (подробнее см.один из предыдущих разделов этого курса). Более подробно рассмотрим использование API браузера в более позднем модуле курса.
Функции или методы
Одну вещь, которую нам нужно прояснить, прежде чем двигаться дальше - технически, встроенные функции браузера не являются функциями — этометоды. Это звучит немного страшно и запутанно, но не волнуйтесь — функции и методы слова во многом взаимозаменяемы, по крайней мере для наших целей, на данном этапе вашего обучения.
Разница между методом и функцией лишь в том, что методы - это функции, определённые внутри объектов. Встроенные функции (методы) браузера и переменные (так называемыесвойства) хранятся внутри структурированных объектов, чтобы сделать код более эффективным и более простым в использовании.
Вам пока не нужно изучать внутреннюю работу структурированных объектов JavaScript - вы можете подождать, пока наш более поздний модуль не научит вас внутренним работам объектов и тому, как создавать свои собственные. На данный момент мы просто хотим устранить любую возможную путаницу метода, в сравнении с функциями - вы, вероятно, встретите оба термина, когда будете смотреть на доступные связанные ресурсы через Интернет.
Пользовательские функции
В этом курсе так же использовалисьпользовательские функции — это функции, которые вы определяете в своём коде, а не внутри браузера. Каждый раз, когда вы видели произвольное слово (имя функции) с круглыми скобками прямо после него, вы использовали пользовательскую функцию. В нашем примереrandom-canvas-circles.html (подробнее см.исходный код) из нашейстатьи о циклах мы включили пользовательскую функциюdraw(), которая выглядит так:
function draw() { ctx.clearRect(0, 0, WIDTH, HEIGHT); for (var i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = "rgba(255,0,0,0.5)"; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); ctx.fill(); }}Эта функция рисует 100 случайных кругов внутри элемента<canvas>. Каждый раз, когда мы хотим это сделать, мы можем вызвать эту функцию следующим образом
draw();вместо того, чтобы каждый раз, когда мы хотим повторить этот код, не писать его заново. И функции могут содержать любой код, который вам нравится - вы можете даже вызывать другие функции внутри своих функций. Вышеупомянутая функция, например, вызывает функциюrandom() три раза, которая выглядит следующим образом:
function random(number) { return Math.floor(Math.random() * number);}Нам понадобилась эта функция, потому что встроенная в браузер функцияMath.random() генерирует случайное дробное число от 0 до 1. Но мы хотим случайное целое число от 0 до указанного числа.
Вызов функций
Скорее всего, вы уже поняли это, но на всякий случай ... чтобы использовать функцию после того, как она была определена, вам нужно запустить или вызвать её. Это делается путём включения имени функции в код где-нибудь, за которым следуют скобки.
function myFunction() { alert("привет");}myFunction();// Единовременный вызов функцииБезымянные функции
Вы можете видеть функции, определённые и вызываемые несколькими разными способами. До этого мы создавали функции таким способом:
function myFunction() { alert("привет");}Но вы также можете создавать функции без имени:
function() { alert('привет');}Такая функция называетсябезымянная функция (или анонимная) — она не имеет имени! Она сама по себе ничего не делает. Обычно такие функции используются вместе с обработчиком событий, например, следующее будет вызывать код внутри функции каждый раз, по нажатию соответствующей кнопки:
var myButton = document.querySelector("button");myButton.onclick = function () { alert("привет");};В приведённом примере требуется, чтобы на странице был элемент<button> (кнопка), которую нужно нажать. Вы уже видели такую структуру несколько раз на протяжении всего курса, подробнее о ней вы узнаете из следующей статьи.
Вы также можете присвоить к переменной анонимную функцию, например:
var myGreeting = function () { alert("привет");};Теперь эту функцию можно вызвать, используя:
myGreeting();Фактически такой способ присваивает переменной имя; вы также можете присвоить функцию значением нескольких переменных, например:
var anotherGreeting = function () { alert("привет");};Теперь функцию можно вызвать, используя любую из переменных
myGreeting();anotherGreeting();Но это может ввести в заблуждение, так что не стоит так делать! При создании функций лучше всего придерживаться следующего вида:
function myGreeting() { alert("привет");}Чаще всего вы будете использовать анонимные функции, чтобы просто запускать код при срабатывания события - например, нажатие кнопки - с помощью обработчика событий. Опять же, это выглядит примерно так:
myButton.onclick = function () { alert("привет"); // При желании, внутри этой функции // можно написать много кода.};Параметры функции
Некоторые функции при их вызове требуют указание параметров — это значения, которые должны быть вставлены в круглые скобки функции, необходимые для корректной работы функции.
Примечание:Параметры иногда называются аргументами, свойствами или атрибутами.
Например встроенная в браузер функцияMath.random() не требует параметров. При вызове, она всегда возвращает случайное число от 0 до 1:
var myNumber = Math.random();Браузерная встроенная функция, работающая со строкой,replace() ожидает два параметра — это подстрока для поиска в основной строке и строка, на которую происходит замена в основной строке:
var myText = "Я строка";var newString = myText.replace("строка", "сосиска");Примечание:Если необходимо указать несколько параметров, их разделяют запятыми.
Следует также отметить, что иногда параметры являются необязательными - вам не нужно их указывать. Если вы этого не сделаете, функция, как правило, примет какое-то поведение по умолчанию. В качестве примера параметр функции массиваjoin() необязателен:
var myArray = ["Я", "люблю", "шоколадных", "лягушек"];var madeAString = myArray.join(" ");// Вернёт 'Я люблю шоколадных лягушек'var madeAString = myArray.join();// Вернёт 'Я,люблю,шоколадных,лягушек'Если не указан параметр для символа соединения / разграничения, по умолчанию используется запятая.
Область видимости функции и конфликты
Давайте немного поговорим оscope - очень важная концепция при работе с функциями. Когда вы создаёте функцию, переменные и другие вещи, определённые внутри функции, находятся внутри их отдельнойобласти (scope), что означает, что они заперты в своих отдельных отсеках, недоступных из других функций или из кода вне функций.
Верхний уровень за пределами всех ваших функций называетсяглобальной областью (global scope). Значения, определённые в глобальном масштабе, доступны извне в коде.
JavaScript настроен таким образом по разным причинам - но главным образом из-за безопасности и организации. Иногда вы не хотите, чтобы переменные были доступны извне в коде - внешние скрипты, которые вы вызывали из других источников, могут начать работать с вашим кодом и вызывать проблемы, потому что они используют одни и те же имена переменных, как и другие части кода , вызывая конфликты. Это может быть сделано злонамеренно или просто случайно.
Например, скажем, у вас есть файл HTML, который вызывается в двух внешних файлах JavaScript, и оба они имеют переменную и определённую функцию, которые используют одно и то же имя:
<!-- Excerpt from my HTML --><script src="first.js"></script><script src="second.js"></script><script> greeting();</script>// first.jsvar name = "Chris";function greeting() { alert("Hello " + name + ": welcome to our company.");}// second.jsvar name = "Zaptec";function greeting() { alert("Our company is called " + name + ".");}Обе функции, которые вы хотите вызвать, называютсяgreeting(), но вы можете получить доступ только к функцииgreeting() файлаfirst.js (функция файлаsecond.js игнорируется). Кроме того, попытка объявить переменнуюname второй раз черезlet в файлеsecond.js приведёт к ошибке.
Примечание:Этот пример можно увидеть в режимеLive на GitHub (см. такжеисходный код).
Хранение частей вашего кода, заблокированных функциями, позволяет избежать таких проблем и считается наилучшей практикой.
Это немного похоже на зоопарк. Львы, зебры, тигры и пингвины находятся в своих собственных ограждениях и имеют доступ только к вещам внутри их вольеров - таким же образом, как и в области функций. Если бы они смогли попасть в другие вольеры, возникли проблемы. В лучшем случае разные животные будут чувствовать себя неудобно в незнакомых местах обитания - лев или тигр будут чувствовать себя ужасно внутри водянистой, ледяной области пингвинов. В худшем случае львы и тигры могут попытаться съесть пингвинов!

Хранитель зоопарка подобен глобальной переменной - он или она имеет ключи для доступа к каждому вольеру, для пополнения запасов пищи, ухода за больными животными и т. д.
Активное обучение: игра с scope
Давайте посмотрим на реальный пример, демонстрирующий обзор.
Сначала создайте локальную копию нашего примераfunction-scope.html. Это содержит две функции, называемые
a()иb(), и три переменные -x,yиz- две из которых определены внутри функций и одна в глобальной области. Он также содержит третью функцию, называемуюoutput(), которая принимает один параметр и выводит его в абзаце на странице.Откройте пример в браузере и в текстовом редакторе.
Откройте консоль JavaScript в инструментах разработчика вашего браузера. В консоли JavaScript введите следующую команду:
jsoutput(x);вы должны увидеть значение переменной
xвывод на экране.Теперь попробуйте ввести следующее в консоли
jsoutput(y);output(z);Оба из них должны возвращать ошибку в строке "ReferenceError: y is not defined". Почему это? Из-за функции scope -
yиzблокируются внутри функцийa()иb(), поэтомуoutput()не может получить к ним доступ при вызове из глобальной области.Однако как насчёт того, когда он вызван изнутри другой функции? Попробуйте отредактировать функции
a()иb(), чтобы они выглядели следующим образом:jsfunction a() { var y = 2; output(y);}function b() { var z = 3; output(z);}Сохраните код и перезагрузите его в своём браузере, затем попробуйте вызвать функции
a()иb()из консоли #"ReferenceError: z is not defined" - это потому, что вызовыoutput()и переменные, которые они пытаются распечатать, не определены внутри одних и тех же областей функций - переменные эффективно невидимы для этих вызовов функций.Примечание:Те же правила определения не применяются к циклу (например,
for() { ... }) и условным блокам (например,if() { ... }) - они выглядят очень похожими, но это не одно и то же! Старайтесь не путать их.Примечание:ReferenceError: "x" is not defined. Ошибка - это одна из наиболее распространённых проблем, с которой вы столкнётесь. Если вы получите эту ошибку, и вы уверены, что определили эту переменную, проверьте, в какой области она находится.
Функции внутри функций
Имейте в виду, что вы можете вызывать функцию из любого места, даже если она внутри другой функции. Это часто используется как способ поддержания чистоты кода. Если у вас есть большая сложная функция, её легче понять, если разбить её на несколько подфункций:
function myBigFunction() { var myValue; subFunction1(); subFunction2(); subFunction3();}function subFunction1() { console.log(myValue);}function subFunction2() { console.log(myValue);}function subFunction3() { console.log(myValue);}Просто убедитесь, что значения, используемые внутри функции, находятся в области видимости. В приведённом выше примере выдаётся ошибкаReferenceError: MyValue is not defined, поскольку хотя переменнаяmyValue определена в той же области, что и вызовы функций, она не определена в определениях функций - фактический код, который запускается при вызове функций. Чтобы это работало, вам нужно передать значение в функцию в качестве параметра, например так:
function myBigFunction() { var myValue = 1; subFunction1(myValue); subFunction2(myValue); subFunction3(myValue);}function subFunction1(value) { console.log(value);}function subFunction2(value) { console.log(value);}function subFunction3(value) { console.log(value);}Заключение
В этой статье были рассмотрены основные понятия, лежащие в основе функций, позволяющие освоить следующий материал, в котором мы получим практические навыки, и научимся создавать собственные функции.
Смотрите также
- Детальное руководство по функциям — описание некоторых дополнительных функций, не описанных в этой статье.
- Описание функций
- Параметры по умолчанию,Стрелочные функции — продвинутая документация