Создаём свою функцию - Изучение веб-разработки

Создаём свою функцию
====================

* Назад
* Обзор: Building blocks
* Далее

Эта статья призвана дать практический опыт на основе теоретических знаний приведённых в предыдущей статье. Попутно мы также объясним некоторые важные детали работы с функциями.

| Предпосылки: | Базовая компьютерная грамотность, базовое понимание HTML и CSS, первые шаги в JavaScript, Функции — блоки кода используемые многократно. |
| --- | --- |
| Задача: | Научить создавать пользовательской функции и объяснить ещё несколько полезных деталей. |

Активное обучение: построение функции
-------------------------------------

Пользовательская функция, которую мы собираемся построить, будет называться `displayMessage()`. Она отобразит настраиваемое окно сообщения на веб-странице и будет действовать как настраиваемая замена встроенной в браузер функции alert(). Мы видели эту функцию раньше. Введите следующую команду в консоли JavaScript браузера на любой странице:

```js
alert("This is a message");
```

Функция `alert` принимает один аргумент - строку, которая отображается в окне сообщения на веб-странице Попробуйте изменить строку, чтобы изменить сообщение.

Функция `alert` ограничена: вы можете изменить текст сообщения, но не получится изменить его стиль, например, цвет, значок или что-то ещё. Создадим сообщение, более интересное по стилю.

**Примечание:** Этот пример будет работать во всех современных браузерах, но стиль может выглядеть немного смешным в более старых браузерах. Мы рекомендуем вам выполнять это упражнение в современном браузере, таком как Firefox, Opera или Chrome.

Основная функция
----------------

Для начала давайте соберём основную функцию.

**Примечание:** Для согласований имён функций нужно следовать тем же правилам, что и правила именования переменных. Отличить имена функций от имён переменных просто: после имён функций указываются круглые скобки, а после имён переменных их нет.

1. Откройте файл function-start.html и скопируйте его себе на компьютер. Код HTML в нем предельно прост: body содержит только одну кнопку. Также здесь представлен базовый CSS для создания настраиваемого окна сообщений и пустой элемент `<script>` для размещения нашего JavaScript.
2. Затем добавьте строку внутри элемента `<script>`:

```js
function displayMessage() {}
```

Мы начинаем с ключевого слова `function`, что означает, что мы определяем функцию. За ним следует имя, которое мы хотим дать нашей функции, набор круглых скобок и набор фигурных скобок. Любые параметры, которые мы хотим задать нашей функции, заключают в круглые скобки, а код, который запускается при вызове функции, находится внутри фигурных скобок.
3. Наконец, добавьте следующий код внутри фигурных скобок:

```js
var html = document.querySelector("html");

var panel = document.createElement("div");
panel.setAttribute("class", "msgBox");
html.appendChild(panel);

var msg = document.createElement("p");
msg.textContent = "This is a message box";
panel.appendChild(msg);

var closeBtn = document.createElement("button");
closeBtn.textContent = "x";
panel.appendChild(closeBtn);

closeBtn.onclick = function () {
  panel.parentNode.removeChild(panel);
};
```

Рассмотрим этот код по строкам (прим. - в оригинале статьи: "bit by bit").

В первой строке используется функция DOM API под именем `document.querySelector()` для выбора элемента `<html>`, сохраняющая ссылку на него в переменной `html`, чтобы позже мы могли с ней что-то сделать:

```js
var html = document.querySelector("html");
```

В следующем разделе используется другая функция DOM API, называемая `Document.createElement()`, применяется для создания элемента `<div>` и сохраняет ссылку на него в переменной, называемой `panel`. Этот элемент будет внешним контейнером нашего окна сообщений.

Затем мы используем ещё одну функцию DOM API, называемую `Element.setAttribute()`, чтобы установить атрибут `class` на нашей панели со значением `msgBox`. Это упрощает стилизацию элемента. Если вы посмотрите на CSS на странице, вы увидите, что мы используем селектор класса `.msgBox` для стилизации окна сообщения и его содержимого.

Наконец, мы вызываем функцию DOM с именем `Node.appendChild()` в переменной `html`, которую мы сохранили ранее, которая вкладывает один элемент в другой как его дочерний элемент. Указываем панель `<div>` как дочерний элемент, который мы хотим вложить внутрь элемента `<html>`. То есть, когда мы создаём какой-то элемент, он не просто будет отображаться на странице сам по себе, нам нужно указать, куда его поместить.

```js
var panel = document.createElement("div");
panel.setAttribute("class", "msgBox");
html.appendChild(panel);
```

В следующих двух разделах используются те же функции `createElement()` и `appendChild()`, которые мы уже видели, чтобы создать два новых элемента: `<p>` и `<button>`, и вставить их на страницу, как дочерних элементов панели `<div>`. Мы используем свойство `Node.textContent`, которое представляет текстовое содержимое элемента, для вставки сообщения внутри абзаца и символ «x» внутрь кнопки. Нажатие/активация этой кнопки будет закрывать окно сообщения.

```js
var msg = document.createElement("p");
msg.textContent = "This is a message box";
panel.appendChild(msg);

var closeBtn = document.createElement("button");
closeBtn.textContent = "x";
panel.appendChild(closeBtn);
```

В заключении мы используем обработчик событий `GlobalEventHandlers.onclick`, чтобы при нажатии кнопки был запущен некоторый код для удаления всей панели со страницы, т.е. для закрытия окна сообщения.

Вкратце, обработчик `onclick` — это свойство, доступное для кнопки (или, фактически, для любого элемента страницы), которое можно установить в функцию, чтобы указать, какой код следует запускать при нажатии кнопки. Вы узнаете об этом больше в нашей статье о последующих событиях. Мы делаем обработчик `onclick` равным анонимной функции, которая содержит код, запускаемый при нажатии кнопки. Строка внутри функции использует функцию `Node.removeChild()` DOM API, чтобы указать, что мы хотим удалить определённый дочерний элемент внутри HTML — в данном случае панель `<div>`.

```js
closeBtn.onclick = function () {
  panel.parentNode.removeChild(panel);
};
```

В принципе, весь этот блок кода генерирует блок HTML, который выглядит так и вставляет его на страницу:

```html
<div class="msgBox">
  <p>This is a message box</p>
  <button>x</button>
</div>
```

Вам не обязательно запоминать сейчас, как работает каждый элемент во всем этом коде. Основная задача — понять структуру и использование функции, при этом мы хотели показать что-то интересное для этого примера.

Вызов функции
-------------

Теперь у вас есть определение функции, написанное в вашем элементе `<script>`, но оно ничего не будет делать в том виде, в каком оно есть.

1. Попробуйте написать следующую строку под своей функцией, чтобы вызвать её:

```js
displayMessage();
```

Эта строка вызывает функцию, немедленно запуская её. Когда вы сохраните код и перезагрузите его в браузере, вы увидите, что небольшое окно сообщения появляется сразу и только один раз.
2. Теперь откройте инструменты разработчика браузера на странице примера, перейдите в консоль JavaScript и снова введите эту строку. Вы увидите, что окно появится снова! Теперь у нас есть функция многократного использования, которую мы можем вызвать в любое время.
 Но мы, вероятно, хотим, чтобы оно появлялось в ответ на действия пользователя и системы. В реальном приложении такое окно сообщения, вероятно, будет вызвано в ответ на доступность новых данных или, если произошла ошибка, или, например, если пользователь пытается удалить свой профиль («вы уверены в этом?»), или если пользователь добавляет новый контакт и операция успешно завершена и т. д.
 В этой демонстрации мы получим окно сообщения, когда пользователь нажимает кнопку.
3. Удалите предыдущую добавленную строку.
4. Затем мы выберем кнопку и сохраним ссылку на неё в переменной. Добавьте следующую строку в свой код, над определением функции:

```js
var btn = document.querySelector("button");
```

5. Наконец, добавьте следующую строку ниже предыдущей:

```js
btn.onclick = displayMessage;
```

Аналогично нашей строке `closeBtn.onclick...` внутри функции здесь мы вызываем некоторый код в ответ на нажатие кнопки. Но в этом случае вместо вызова анонимной функции, содержащей некоторый код, мы вызываем имя нашей функции напрямую.
6. Сохраните и обновите страницу. Теперь вы должны увидеть окно с сообщением, когда вы нажимаете кнопку.

Возможно, вам интересно, почему мы не включили круглые скобки после имени функции. Это связано с тем, что нам нужно не сразу вызвать функцию, а только после нажатия кнопки. Если вы попытаетесь изменить строку на

```js
btn.onclick = displayMessage();
```

сохраните и перезагрузите страницу, вы увидите, что окно сообщения появляется без нажатия кнопки! Скобки в этом контексте иногда называют «оператором вызова функции». Вы используете их только в том случае, если хотите немедленно запустить функцию в текущей области. В этом же отношении код внутри анонимной функции не запускается сразу, так как он находится внутри области функций.

Если вы пробовали последний эксперимент, перед тем, как продолжить, обязательно отмените последнее изменение.

Улучшение функции с параметрами
-------------------------------

В нынешнем виде функция по-прежнему не очень полезна — мы не хотим показывать одно и то же сообщение по умолчанию каждый раз. Давайте улучшим нашу функцию, добавив некоторые параметры, позволяющие нам называть её различными вариантами.

1. Прежде всего, обновите первую строку функции:

```js
function displayMessage() {
```

к этому:

```js
function displayMessage(msgText, msgType) {
```

Теперь, когда мы вызываем функцию, мы можем предоставить два значения переменных в круглых скобках, чтобы указать сообщение для отображения в окне сообщения, а также тип сообщения.
2. Чтобы использовать первый параметр, обновите следующую строку внутри своей функции:

```js
msg.textContent = "This is a message box";
```

к этому:

```js
msg.textContent = msgText;
```

3. И последнее, но не менее важное: теперь вам нужно обновить вызов функции, чтобы включить в него обновлённый текст сообщения. Измените следующую строку:

```js
btn.onclick = displayMessage;
```

к этому блоку:

```js
btn.onclick = function () {
  displayMessage("Woo, this is a different message!");
};
```

Если мы хотим указать параметры в круглых скобках для вызываемой нами функции, то мы не можем назвать её напрямую, нам нужно поместить её в анонимную функцию, чтобы она не находилась непосредственно в области видимости и, следовательно, не вызывалась немедленно. Теперь она не будет вызываться до нажатия кнопки.
4. Перезагрузите и протестируйте код ещё раз, и вы увидите, что он по-прежнему работает, только теперь вы также можете изменять сообщение внутри параметра, чтобы отображать разные сообщения в окне.
### Более сложный параметр

Переход к следующему параметру. Это потребует немного больше работы. Установим его так, чтобы в зависимости от того, какой параметр `msgType` установлен, функция отображала другой значок и другой цвет фона.

1. Для начала, загрузите значки, необходимые для этого упражнения (warning и chat [тут чёрные иконки на чёрном фоне... тролли на GitHub]) из GitHub. Сохраните их в новой папке `icons` в том же месте, что и ваш HTML-файл.

**Примечание:** иконки warning и chat были найдены на iconfinder.com, и разработаны Nazarrudin Ansyari. Спасибо! (Фактические страницы значков были перемещены или удалены.)
2. Затем найдите CSS внутри вашего HTML-файла. Мы сделаем несколько изменений, чтобы освободить место для иконок. Во-первых, обновите ширину `.msgBox`:

```css
width: 200px;
```

измените на:

```css
width: 242px;
```

3. Затем добавьте следующие строки в правило `.msgBox p { ... }` :

```css
padding-left: 82px;
background-position: 25px center;
background-repeat: no-repeat;
```

4. Теперь нам нужно добавить код в нашу функцию `displayMessage()` для обработки отображений значков. Добавьте следующий блок чуть выше закрывающей фигурной скобки "`}`" вашей функции:

```js
if (msgType === "warning") {
  msg.style.backgroundImage = "url(icons/warning.png)";
  panel.style.backgroundColor = "red";
} else if (msgType === "chat") {
  msg.style.backgroundImage = "url(icons/chat.png)";
  panel.style.backgroundColor = "aqua";
} else {
  msg.style.paddingLeft = "20px";
}
```

Здесь, если параметр `msgType` установлен как `'warning'`, отображается значок предупреждения, а цвет фона панели устанавливается красным. Если для него установлено значение`'chat'`, отображается значок чата, а цвет фона панели становится голубым. Если параметр `msgType` не задан вообще (или задано что-то другое), тогда вступает в действие `else {...}`, а абзацу просто присваиваются заданные по умолчанию отступы, нет никакого значка, при этом не задаётся цвет фона окна сообщения. Это обеспечивает состояние по умолчанию, если не указан параметр `msgType`, что означает, что это необязательный параметр!
5. Давайте протестируем нашу обновлённую функцию, попробуем обновить вызов displayMessage () из этого:

```js
displayMessage("Woo, this is a different message!");
```

к одному из них:

```js
displayMessage("Your inbox is almost full — delete some mails", "warning");
displayMessage("Brian: Hi there, how are you today?", "chat");
```

Вот, насколько полезной становится наша (теперь не очень) маленькая функция.

**Примечание:** Если у вас возникли проблемы с запуском примера, не стесняйтесь проверять свой код на готовой версии GitHub (см. также в режиме реального времени) или обратитесь к нам за помощью.

Вывод
-----

В этой статье мы познакомились со всем процессом создания практической пользовательской функции, которую с небольшими доработками можно перенести в реальный проект. В следующей статье мы рассмотрим ещё одну важную концепцию — возвращаемые значения функций.

* Назад
* Обзор: Building blocks
* Далее


Функции — Переиспользуемые блоки кода - Изучение веб-разработки

Функции — Переиспользуемые блоки кода
=====================================

* Назад
* Обзор: Building blocks
* Далее

Другая важная концепция в кодировании — **функции** — позволяют хранить фрагмент кода, который выполняет одну задачу внутри определённого блока, а затем вызывать этот код всякий раз, когда вам это нужно, используя одну короткую команду, вместо того, чтобы вводить один и тот же код несколько раз.

В этой статье мы рассмотрим фундаментальные концепции функций, такие как базовый синтаксис, способы вызова и их определения, область действия и параметры.

| Предпосылки: | Начальная компьютерная грамотность, основы HTML и CSS, первые шаги JavaScript. |
| --- | --- |
| Цель: | Понять фундаментальные основы функций языка JavaScript. |

Где можно встретить функции?
----------------------------

В JavaScript, вы везде уведите функции. На самом деле, мы пользовались функциями на протяжении всего курса; только мы не говорили об этом слишком часто. Теперь наступило время, чтобы поговорить о функциях более конкретно и разобрать их синтаксис.

В значительном количестве случаев, когда вы пользуетесь структурой JavaScript, в которой есть пара обычных скобок — `()` — и при этом, это не является структурой типа цикл for, while, или do...while цикл, или if...else конструкция, вы используете функцию.

Встроенные функции браузера
---------------------------

В этом курсе мы использовали функции, встроенные в браузер. Каждый раз, когда мы манипулировали текстовой строкой, например:

```js
var myText = "Я строка";
var newString = myText.replace("строка", "сосиска");
console.log(newString);
// Функция строки replace() принимает строку,
// заменяет одну строку на другую, и возвращает
// новую строку с заменённым содержимым
```

Или каждый раз, когда мы манипулировали массивом:

```js
var myArray = ["Я", "люблю", "шоколадных", "лягушек"];
var madeAString = myArray.join(" ");
console.log(madeAString);
// Функция join() принимает массив, соединяет
// все элементы массива вместе в одну строку,
// и возвращает эту новую строку
```

Или каждый раз, когда мы генерировали случайное число:

```js
var myNumber = Math.random();
// Функция random() генерирует случайное число от 0 до 1,
// и возвращает это число
```

...мы использовали функции!

**Примечание:** вы можете вставить эти строки в консоль вашего браузера, чтобы посмотреть, как работают эти функции.

Фактически, часть кода, который вы вызываете, когда ссылаетесь на встроенную функцию браузера (воображаемое слово для её запуска или выполнения), не может быть написана на JavaScript — многие из этих функций вызывают части фонового кода браузера, который написан в основном на системных языках низкого уровня, таких как C ++, а не на веб-языках, таких как JavaScript.

Имейте в виду, что некоторые встроенные функции браузера не являются частью основного языка JavaScript — некоторые из них являются частью API браузера, которые основываются на языке по умолчанию, чтобы обеспечить ещё большую функциональность (подробнее см. один из предыдущих разделов этого курса). Более подробно рассмотрим использование API браузера в более позднем модуле курса.

Функции или методы
------------------

Одну вещь, которую нам нужно прояснить, прежде чем двигаться дальше - технически, встроенные функции браузера не являются функциями — это **методы**. Это звучит немного страшно и запутанно, но не волнуйтесь — функции и методы слова во многом взаимозаменяемы, по крайней мере для наших целей, на данном этапе вашего обучения.

Разница между методом и функцией лишь в том, что методы - это функции, определённые внутри объектов. Встроенные функции (методы) браузера и переменные (так называемые **свойства**) хранятся внутри структурированных объектов, чтобы сделать код более эффективным и более простым в использовании.

Вам пока не нужно изучать внутреннюю работу структурированных объектов JavaScript - вы можете подождать, пока наш более поздний модуль не научит вас внутренним работам объектов и тому, как создавать свои собственные. На данный момент мы просто хотим устранить любую возможную путаницу метода, в сравнении с функциями - вы, вероятно, встретите оба термина, когда будете смотреть на доступные связанные ресурсы через Интернет.

Пользовательские функции
------------------------

В этом курсе так же использовались **пользовательские функции** — это функции, которые вы определяете в своём коде, а не внутри браузера. Каждый раз, когда вы видели произвольное слово (имя функции) с круглыми скобками прямо после него, вы использовали пользовательскую функцию. В нашем примере random-canvas-circles.html (подробнее см. исходный код) из нашей статьи о циклах мы включили пользовательскую функцию `draw()`, которая выглядит так:

```js
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>`. Каждый раз, когда мы хотим это сделать, мы можем вызвать эту функцию следующим образом

```js
draw();
```

вместо того, чтобы каждый раз, когда мы хотим повторить этот код, не писать его заново. И функции могут содержать любой код, который вам нравится - вы можете даже вызывать другие функции внутри своих функций. Вышеупомянутая функция, например, вызывает функцию `random()` три раза, которая выглядит следующим образом:

```js
function random(number) {
  return Math.floor(Math.random() \* number);
}
```

Нам понадобилась эта функция, потому что встроенная в браузер функция Math.random() генерирует случайное дробное число от 0 до 1. Но мы хотим случайное целое число от 0 до указанного числа.

Вызов функций
-------------

Скорее всего, вы уже поняли это, но на всякий случай ... чтобы использовать функцию после того, как она была определена, вам нужно запустить или вызвать её. Это делается путём включения имени функции в код где-нибудь, за которым следуют скобки.

```js
function myFunction() {
  alert("привет");
}

myFunction();
// Единовременный вызов функции
```

Безымянные функции
------------------

Вы можете видеть функции, определённые и вызываемые несколькими разными способами. До этого мы создавали функции таким способом:

```js
function myFunction() {
  alert("привет");
}
```

Но вы также можете создавать функции без имени:

```js
function() {
  alert('привет');
}
```

Такая функция называется **безымянная функция** (или анонимная) — она не имеет имени! Она сама по себе ничего не делает. Обычно такие функции используются вместе с обработчиком событий, например, следующее будет вызывать код внутри функции каждый раз, по нажатию соответствующей кнопки:

```js
var myButton = document.querySelector("button");

myButton.onclick = function () {
  alert("привет");
};
```

В приведённом примере требуется, чтобы на странице был элемент `<button>` (кнопка), которую нужно нажать. Вы уже видели такую структуру несколько раз на протяжении всего курса, подробнее о ней вы узнаете из следующей статьи.

Вы также можете присвоить к переменной анонимную функцию, например:

```js
var myGreeting = function () {
  alert("привет");
};
```

Теперь эту функцию можно вызвать, используя:

```js
myGreeting();
```

Фактически такой способ присваивает переменной имя; вы также можете присвоить функцию значением нескольких переменных, например:

```js
var anotherGreeting = function () {
  alert("привет");
};
```

Теперь функцию можно вызвать, используя любую из переменных

```js
myGreeting();
anotherGreeting();
```

Но это может ввести в заблуждение, так что не стоит так делать! При создании функций лучше всего придерживаться следующего вида:

```js
function myGreeting() {
  alert("привет");
}
```

Чаще всего вы будете использовать анонимные функции, чтобы просто запускать код при срабатывания события - например, нажатие кнопки - с помощью обработчика событий. Опять же, это выглядит примерно так:

```js
myButton.onclick = function () {
  alert("привет");
  // При желании, внутри этой функции
  // можно написать много кода.
};
```

Параметры функции
-----------------

Некоторые функции при их вызове требуют указание параметров — это значения, которые должны быть вставлены в круглые скобки функции, необходимые для корректной работы функции.

**Примечание:** Параметры иногда называются аргументами, свойствами или атрибутами.

Например встроенная в браузер функция Math.random() не требует параметров. При вызове, она всегда возвращает случайное число от 0 до 1:

```js
var myNumber = Math.random();
```

Браузерная встроенная функция, работающая со строкой, replace() ожидает два параметра — это подстрока для поиска в основной строке и строка, на которую происходит замена в основной строке:

```js
var myText = "Я строка";
var newString = myText.replace("строка", "сосиска");
```

**Примечание:** Если необходимо указать несколько параметров, их разделяют запятыми.

Следует также отметить, что иногда параметры являются необязательными - вам не нужно их указывать. Если вы этого не сделаете, функция, как правило, примет какое-то поведение по умолчанию. В качестве примера параметр функции массива join() необязателен:

```js
var myArray = ["Я", "люблю", "шоколадных", "лягушек"];
var madeAString = myArray.join(" ");
// Вернёт 'Я люблю шоколадных лягушек'
var madeAString = myArray.join();
// Вернёт 'Я,люблю,шоколадных,лягушек'
```

Если не указан параметр для символа соединения / разграничения, по умолчанию используется запятая.

Область видимости функции и конфликты
-------------------------------------

Давайте немного поговорим о scope (en-US) - очень важная концепция при работе с функциями. Когда вы создаёте функцию, переменные и другие вещи, определённые внутри функции, находятся внутри их отдельной **области (scope)**, что означает, что они заперты в своих отдельных отсеках, недоступных из других функций или из кода вне функций.

Верхний уровень за пределами всех ваших функций называется **глобальной областью (global scope)**. Значения, определённые в глобальном масштабе, доступны извне в коде.

JavaScript настроен таким образом по разным причинам - но главным образом из-за безопасности и организации. Иногда вы не хотите, чтобы переменные были доступны извне в коде - внешние скрипты, которые вы вызывали из других источников, могут начать работать с вашим кодом и вызывать проблемы, потому что они используют одни и те же имена переменных, как и другие части кода , вызывая конфликты. Это может быть сделано злонамеренно или просто случайно.

Например, скажем, у вас есть файл HTML, который вызывается в двух внешних файлах JavaScript, и оба они имеют переменную и определённую функцию, которые используют одно и то же имя:

```html
<!-- Excerpt from my HTML -->
<script src="first.js"></script>
<script src="second.js"></script>
<script>
 greeting();
</script>
```

```js
// first.js
var name = "Chris";
function greeting() {
  alert("Hello " + name + ": welcome to our company.");
}
```

```js
// second.js
var name = "Zaptec";
function greeting() {
  alert("Our company is called " + name + ".");
}
```

Обе функции, которые вы хотите вызвать, называются `greeting()`, но вы можете получить доступ только к функции `greeting()` файла `first.js` (функция файла `second.js` игнорируется). Кроме того, попытка объявить переменную `name` второй раз через `let` в файле `second.js` приведёт к ошибке.

**Примечание:** Этот пример можно увидеть в режиме Live на GitHub (см. также исходный код).

Хранение частей вашего кода, заблокированных функциями, позволяет избежать таких проблем и считается наилучшей практикой.

Это немного похоже на зоопарк. Львы, зебры, тигры и пингвины находятся в своих собственных ограждениях и имеют доступ только к вещам внутри их вольеров - таким же образом, как и в области функций. Если бы они смогли попасть в другие вольеры, возникли проблемы. В лучшем случае разные животные будут чувствовать себя неудобно в незнакомых местах обитания - лев или тигр будут чувствовать себя ужасно внутри водянистой, ледяной области пингвинов. В худшем случае львы и тигры могут попытаться съесть пингвинов!

![](/ru/docs/Learn/JavaScript/Building_blocks/Functions/mdn-mozilla-zoo.png)

Хранитель зоопарка подобен глобальной переменной - он или она имеет ключи для доступа к каждому вольеру, для пополнения запасов пищи, ухода за больными животными и т. д.

### Активное обучение: игра с scope

Давайте посмотрим на реальный пример, демонстрирующий обзор.

1. Сначала создайте локальную копию нашего примера function-scope.html. Это содержит две функции, называемые `a()` и `b()`, и три переменные - `x`, `y` и `z` - две из которых определены внутри функций и одна в глобальной области. Он также содержит третью функцию, называемую `output()`, которая принимает один параметр и выводит его в абзаце на странице.
2. Откройте пример в браузере и в текстовом редакторе.
3. Откройте консоль JavaScript в инструментах разработчика вашего браузера. В консоли JavaScript введите следующую команду:

```js
output(x);
```

вы должны увидеть значение переменной `x` вывод на экране.
4. Теперь попробуйте ввести следующее в консоли

```js
output(y);
output(z);
```

Оба из них должны возвращать ошибку в строке "ReferenceError: y is not defined". Почему это? Из-за функции scope - `y` и `z` блокируются внутри функций `a()` и `b()`, поэтому `output()` не может получить к ним доступ при вызове из глобальной области.
5. Однако как насчёт того, когда он вызван изнутри другой функции? Попробуйте отредактировать функции `a()` и `b()`, чтобы они выглядели следующим образом:

```js
function a() {
  var y = 2;
  output(y);
}

function b() {
  var z = 3;
  output(z);
}
```

Сохраните код и перезагрузите его в своём браузере, затем попробуйте вызвать функции `a()` и `b()` из консоли JavaScript:

```js
a();
b();
```

вы должны увидеть значения y и z, выводимые на странице. Это отлично работает, так как функция `output()` вызывается внутри других функций - в той же области, где переменные, которые она печатает, определяются в каждом случае. `output()` доступен из любого места, поскольку он определён в глобальной области.
6. Теперь попробуйте обновить свой код следующим образом:

```js
function a() {
  var y = 2;
  output(x);
}

function b() {
  var z = 3;
  output(x);
}
```

Сохраните и перезагрузите снова и повторите попытку в консоли JavaScript:
7.
```js
a();
b();
```

Оба вызова `a()` и `b()` должны выводить значение x - 1. Они работают нормально, потому что, хотя вызовы `output()` не находятся в той же области, где определено `x`, `x` - глобальная переменная, поэтому она доступна внутри всего кода, везде
8. Наконец, попробуйте обновить свой код следующим образом:

```js
function a() {
  var y = 2;
  output(z);
}

function b() {
  var z = 3;
  output(y);
}
```

Сохраните и перезагрузите снова и повторите попытку в консоли JavaScript:

```js
a();
b();
```

На этот раз вызовы `a()` и `b()` возвратят эту раздражающую ошибку "ReferenceError: z is not defined" - это потому, что вызовы `output()` и переменные, которые они пытаются распечатать, не определены внутри одних и тех же областей функций - переменные эффективно невидимы для этих вызовов функций.

**Примечание:** Те же правила определения не применяются к циклу (например, `for() { ... }`) и условным блокам (например, `if() { ... }`) - они выглядят очень похожими, но это не одно и то же! Старайтесь не путать их.

**Примечание:** ReferenceError: "x" is not defined. Ошибка - это одна из наиболее распространённых проблем, с которой вы столкнётесь. Если вы получите эту ошибку, и вы уверены, что определили эту переменную, проверьте, в какой области она находится.

### Функции внутри функций

Имейте в виду, что вы можете вызывать функцию из любого места, даже если она внутри другой функции. Это часто используется как способ поддержания чистоты кода. Если у вас есть большая сложная функция, её легче понять, если разбить её на несколько подфункций:

```js
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` определена в той же области, что и вызовы функций, она не определена в определениях функций - фактический код, который запускается при вызове функций. Чтобы это работало, вам нужно передать значение в функцию в качестве параметра, например так:

```js
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);
}
```

Заключение
----------

В этой статье были рассмотрены основные понятия, лежащие в основе функций, позволяющие освоить следующий материал, в котором мы получим практические навыки, и научимся создавать собственные функции.

Смотрите также
--------------

* Детальное руководство по функциям — описание некоторых дополнительных функций, не описанных в этой статье.
* Описание функций
* Параметры по умолчанию, Стрелочные функции — продвинутая документация

* Назад
* Обзор: Building blocks
* Далее


Принятие решений в вашем коде — условные конструкции - Изучение веб-разработки

Принятие решений в вашем коде — условные конструкции
====================================================

* Обзор: Building blocks
* Далее

Во многих языках программирования код должен иметь возможность принимать решения на основе введённых пользователем данных. Например, в игре, если у пользователя осталось 0 жизней, то игра завершается. В приложении о погоде утром отображается восход солнца, а вечером звезды и луна. В этой статье мы рассмотрим как в JavaScript работают так называемые "условия".

| Необходимое условие: | Базовая компьютерная грамотность, базовое понимание HTML и CSS, JavaScript first steps. |
| --- | --- |
| Цель: | Понять принципы использования операторов условий в JavaScript. |

Выбор одного условия!
---------------------

Люди (и животные) принимают какие-либо решения всю жизнь, от малозначимых ("стоит ли мне съесть одну печеньку или две?") до жизнеопределяющих ("стоит ли мне остаться дома и работать на ферме отца или переехать в другую страну и изучать астрофизику?")

Операторы условия в JavaScript позволяют нам указать разного рода действия в зависимости от выбранного пользователем или системой ответа (например одна печенька или две) и связать его с действием (результатом), например, результатом "съесть одну печеньку" будет "все ещё буду чувствовать себя голодным", а результатом "съесть две печеньки" будет "буду чувствовать себя сытым, но мама меня поругает за то, что я съел все сладости".

![](/ru/docs/Learn/JavaScript/Building_blocks/conditionals/cookie-choice-small.png)

Оператор if ... else
--------------------

Давайте глянем на наиболее распространённый тип условного оператора, который вы будете использовать в JavaScript — `if ... else` оператор.

### Базовый if ... else синтаксис

Базовый `if...else` синтаксис выглядит как pseudocode:
```

if (condition) {
  code to run if condition is true
} else {
  run some other code instead
}
```

Что мы имеем:

1. Ключевое слово `if` расположено перед круглыми скобками.
2. Условие для проверки (condition), расположено внутри круглых скобок (например "это значение больше другого значения?", или "это значение существует?"). Это условие использует операторы сравнения (comparison operators), которые мы изучим позже, и возвратит нам `true` или `false`.
3. Внутри скобок { } расположен код, который будет выполняться только в том случае, если условие (condition) верно (`true)`.
4. Ключевое слово `else (иначе)`.
5. Ещё скобки { }, код внутри которых выполнится, только если условие не верно (не `true)`.

Этот код довольно читабелен — он говорит "**if (если)** **condition (условие)** возвращает `true (истина)`, запусти код A, **else (иначе)** запусти B"

Стоит заметить, что `else` и второй блок скобок { } не обязателен — следующий код так же будет работать:
```

if (condition) {
  код, который должен выполнить, если условие истина
}

какой-то другой код
```

Тем не менее, следует быть осторожным — в случае, если код внутри вторых скобок { } не контролируется условием, то этот код будет выполняться **всегда**. Это не плохо, просто вы должны помнить об этом, чаще вы хотите запустить один кусок кода *или* другой, но не оба.

И, наконец, иногда вы можете встретить код `if...else` без фигурных скобок в сокращённой форме:
```

if (condition) code to run if condition is true
else run some other code instead
```

Это абсолютно рабочий код, но он менее читаем, лучше использовать фигурные скобки, новые строки и отступы.

### Реальный пример

Чтобы лучше понять синтаксис, давайте рассмотрим реальный пример. Представьте, что мать или отец попросили помочь с работой по дому своего ребёнка. Родитель может сказать: "Если ты поможешь мне с покупками, то я дам тебе дополнительные деньги на карманные расходы, которые ты сможешь потратить на игрушку, какую захочешь". В JavaScript, мы можем представить это так:

```js
var shoppingDone = false;

if (shoppingDone === true) {
  var childsAllowance = 10;
} else {
  var childsAllowance = 5;
}
```

В этом коде, как показано, всегда будет `shoppingDone` равный `false`, что означает разочарование для нашего бедного ребёнка. Мы должны предоставить механизм для родителя, чтобы установить для переменной `shoppingDone` значение `true` , если ребёнок помог с покупками.

**Примечание:** вы можете увидеть больше в полной версии этого примера на GitHub (также посмотреть как он работает вживую.)

### else if

В предыдущем примере предоставлено два выбора, или результата — но что, если мы хотим больше, чем два?

Существует способ привязать дополнительные варианты/результаты к вашему `if...else` — использовать `else if`. Для каждого дополнительного выбора требуется дополнительный блок, который нужно расположить между `if() { ... }` и `else { ... }` — проверьте следующий более сложный пример, который может быть частью простого приложения прогноза погоды:

```html
<label for="weather">Выберите тип погоды сегодня: </label>
<select id="weather">
  <option value="">--Сделайте выбор--</option>
  <option value="sunny">Солнечно</option>
  <option value="rainy">Дождливо</option>
  <option value="snowing">Снежно</option>
  <option value="overcast">Облачно</option>
</select>

<p></p>
```

```js
var select = document.querySelector("select");
var para = document.querySelector("p");

select.addEventListener("change", setWeather);

function setWeather() {
  var choice = select.value;

  if (choice === "sunny") {
    para.textContent =
      "Сегодня хорошо и солнечно. Носите шорты! Идите на пляж, или в парк, и купите мороженое.";
  } else if (choice === "rainy") {
    para.textContent =
      "Дождь падает за окном; возьмите плащ и зонт, и не находитесь слишком долго на улице.";
  } else if (choice === "snowing") {
    para.textContent =
      "Снег падает - морозно! Лучше всего посидеть с чашкой горячего шоколада или слепить снеговика.";
  } else if (choice === "overcast") {
    para.textContent =
      "Дождя нет, но небо серое и мрачное; он все может измениться в любую минуту, поэтому на всякий случай возьмите дождевик.";
  } else {
    para.textContent = "";
  }
}
```

1. Здесь у нас есть элемент HTML `<select>` который позволяет нам выбирать разные варианты погоды и простой абзац.
2. В JavaScript мы создаём ссылки на элементы `<select>` и `<p>` и добавляем обработчик события элемента `<select>`, чтобы при его изменении значения запускалась функция `setWeather()`.
3. Когда функция будет запущена, первоначально мы определим значение переменной `choice`, которая равна выбранному значению в элементе `<select>`. Затем мы используем условный оператор для отображения текста внутри абзаца в зависимости от того, какое значение у переменной `choice`. Обратите внимание, как все условия проверяются в `else if() {...}` блоках, за исключением первого, который использует `if() {...}` блок.
4. Последний выбор, внутри `else {...}` блока, в основном является «последним средством» — код внутри него будет запущен, если ни одно из условий не будет `true`. В этом случае он служит для удаления текста из абзаца, если ничего не выбрано, например, если пользователь решает повторно выбрать опцию "--Сделайте выбор--" которая указана в начале.

**Примечание:** вы можете найти этот пример на GitHub (также увидеть как он работает)

### Примечание об операторах сравнения

Операторы сравнения используют для проверки условий внутри наших условных операторов. Сначала мы посмотрели на операторы сравнения в нашей статье Базовая математика в JavaScript — цифры и операторы . Наш выбор это:

* `===` и `!==` — проверяет одно значение идентично или не идентично другому.
* `<` и `>` — проверяет одно значение меньше или больше, чем другое.
* `<=` и `>=` — проверяет одно значение меньше или равно, либо больше или равно другому.

**Примечание:** Просмотрите материал по предыдущей ссылке, если вы хотите освежить свою память.

Мы хотели бы особо обратить внимание на проверку булевых значений (`true`/`false`), и общий шаблон, который вы будете встречать снова и снова. Любое значение, которое не есть `false`, `undefined`, `null`, `0`, `NaN`, или пустая строка (`''`) фактически возвращает `true` при тестировании как условного оператора. Поэтому вы можете просто использовать имя собственной переменной, чтобы проверить, равна ли она `true`, или существует (т. е. переменная не равна undefined). Например:

```js
var cheese = "Cheddar";

if (cheese) {
  console.log("Ура! Есть сыр для приготовления бутерброда.");
} else {
  console.log("Сегодня нет сыра для бутерброда.");
}
```

И, возвращаясь к нашему предыдущему примеру о ребёнке, выполняющем поручение своего родителя, вы можете это записать так:

```js
var shoppingDone = false;

if (shoppingDone) {
  // не нужно явно указывать '=== true'
  var childsAllowance = 10;
} else {
  var childsAllowance = 5;
}
```

### Вложенность if ... else

Вполне нормально использовать один условный оператор `if...else` внутри другого — вложить их. Например, мы могли бы обновить наше приложение прогноза погоды, чтобы показать ещё один набор вариантов в зависимости от температуры:

```js
if (choice === "sunny") {
  if (temperature < 86) {
    para.textContent =
      "Сейчас " +
      temperature +
      " градусов по фаренгейту — хорошо и солнечно. Идите на пляж, или в парк, и купите мороженое.";
  } else if (temperature >= 86) {
    para.textContent =
      "Сейчас " +
      temperature +
      " градусов по фаренгейту — Жара! Если вы хотите выйти на улицу, обязательно используйте солнцезащитный крем.";
  }
}
```

Несмотря на то, что весь код работает вместе, каждый условный оператор `if...else` работает полностью отдельно от другого.

### Логические операторы: И, ИЛИ и НЕ

Если вы хотите проверить несколько условий без записи вложенных `if...else` условий, логические операторы (en-US) помогут вам. При использовании в условиях, первые два оператора делают следующее:

* `&&` — И; позволяет объединить два или более выражения так, что каждое из них отдельно должно иметь значение `true` , чтобы в итоге общее выражение имело значение `true`.
* `||` — ИЛИ; позволяет объединить два или более выражения так, что одно или несколько из них должно иметь значение `true` , чтобы в итоге общее выражение имело значение `true`.

Чтобы дать вам пример оператора И, предыдущий фрагмент кода можно переписать так:

```js
if (choice === "sunny" && temperature < 86) {
  para.textContent =
    "Сейчас " +
    temperature +
    " градусов по фаренгейту — хорошо и солнечно. Идите на пляж, или в парк, и купите мороженое.";
} else if (choice === "sunny" && temperature >= 86) {
  para.textContent =
    "Сейчас " +
    temperature +
    " градусов по фаренгейту — Жара! Если вы хотите выйти на улицу, обязательно используйте солнцезащитный крем.";
}
```

Так, для примера, первый блок кода выполнится только в том случае, если `choice === 'sunny'` *и*`temperature < 86` вернут значение `true`.

Давайте посмотрим на быстрый пример оператора ИЛИ:

```js
if (iceCreamVanOutside || houseStatus === "в огне") {
  //если подъехал фургон с мороженым или дом горит
  console.log("Вы должны быстро покинуть дом.");
} else {
  console.log("Вероятно, можно в нем оставаться.");
}
```

Последний тип логического оператора НЕ, выраженный `!` оператором, можно использовать для отрицания выражения. Давайте объединим его с ИЛИ в приведённом выше примере:

```js
if (!(iceCreamVanOutside || houseStatus === "on fire")) {
  console.log("Вероятно, можно в нем оставаться.");
} else {
  console.log("Вы должны быстро покинуть дом.");
}
```

В этом фрагменте, если условие ИЛИ возвращает `true`, оператор НЕ будет отрицать это и выражение вернёт `false`.

Можно сочетать любое количество логических операторов, в любой последовательности и в любой комбинации. В следующем примере код в блоке будет выполняться только в том случае, если оба условия с ИЛИ возвращают true, а следовательно, и оператор И возвращает true:

```js
if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === "Steve")) {
  // код выполняется
}
```

Распространённой ошибкой при использовании логического оператора ИЛИ в условном выражении является указание переменной, значение которой нужно проверить со списком возможных значений этой переменной, разделённых операторами `||` (ИЛИ). Например.

```js
if (x === 5 || 7 || 10 || 20) {
  // выполнить код
}
```

В данном примере условие в `if(...)` всегда будет оцениваться как true, поскольку 7 (или любое другое ненулевое значение) всегда будет оцениваться как true. Фактически, это условие гласит «если х равен 5, или 7 является true». Но нам требуется совсем не это. Чтобы достичь нужной цели, придётся выполнять полноценную проверку после каждого оператора ИЛИ:

```js
if (x === 5 || x === 7 || x === 10 || x === 20) {
  // выполнить код
}
```

Оператор switch
---------------

Выражения `if...else` отлично справляются с добавлением условного кода, однако они не лишены недостатков. Они хорошо подходят для ситуации, когда имеется всего пара вариантов развития событий, каждый из которых имеет блок с приемлемым количеством кода, а также в случаях, когда условие является довольно сложным и включает несколько логических операторов. Если же нам требуется всего лишь задать переменную для определённого выбранного значения или напечатать конкретную фразу при определённом условии, изученный нами синтаксис может оказаться довольно громоздким, особенно если имеется большое количество вариантов выбора.

В этом случае нам поможет оператор `switch` – он принимает одно единственное выражение или значение, а затем просматривает ряд вариантов, пока не найдут вариант, соответствующий этому значению, после чего выполняет код, назначенный этому варианту. Вот пример использования этого оператора:
```

switch (выражение) {
  case choice1:
    выполнить этот код
    break;

  case choice2:
    выполнить этот код, а не предыдущий
    break;

  // вариантов может быть любое количество

  default:
    а вообще-то, выполнить только этот код
}
```

Что мы имеем:

1. Ключевое слово `switch`, за которым следует пара круглых скобок.
2. В скобках приводится выражение или значение.
3. Ключевое слово `case`, за которым следует вариант выбора (именно он проверяется на соответствие выражению или значению) и двоеточие.
4. Код, который будет выполняться, если вариант совпадает с выражением.
5. Оператор `break`, за которым следует точка с запятой. Если вариант совпал с выражением или значением, браузер закончит выполнять блок кода, дойдя до оператора `break`, и перейдёт к выполнению кода, расположенного после оператора switch.
6. Вариантов выбора (пункты 3–5) может быть любое количество.
7. Ключевое слово `default` используется точно также, как любой другой вариант выбора (пункты 3–5) за тем исключением, что после `default` нет других вариантов выбора, поэтому инструкция `break` не требуется, никакого кода дальше нет. Это вариант выбора по умолчанию, выбираемый, если ни один из других вариантов не совпал с выражением.

**Примечание:** Вариант выбора `default` может быть пропущен, если выражение гарантированно совпадёт с одним из вариантов выбора. В противном случае вариант `default` необходим.

### Пример оператора switch

Давайте рассмотрим реальный пример — перепишем наше приложение прогноза погоды с использованием оператора switch:

```html
<label for="weather">Выберите тип погоды сегодня: </label>
<select id="weather">
  <option value="">--Сделайте выбор--</option>
  <option value="sunny">Солнечно</option>
  <option value="rainy">Дождливо</option>
  <option value="snowing">Снежно</option>
  <option value="overcast">Облачно</option>
</select>

<p></p>
```

```js
var select = document.querySelector("select");
var para = document.querySelector("p");

select.addEventListener("change", setWeather);

function setWeather() {
  var choice = select.value;

  switch (choice) {
    case "sunny":
      para.textContent =
        "Сегодня хорошо и солнечно. Наденьте шорты! Идите на пляж или в парк, и купите мороженое.";
      break;
    case "rainy":
      para.textContent =
        "На улице дождь. Возьмите плащ и зонт, и не гуляйте слишком долго";
      break;
    case "snowing":
      para.textContent =
        "Идёт снег - морозно! Лучше всего посидеть с чашкой горячего шоколада или слепить снеговика.";
      break;
    case "overcast":
      para.textContent =
        "Дождя нет, но небо серое и мрачное; он все может измениться в любую минуту, поэтому на всякий случай возьмите дождевик.";
      break;
    default:
      para.textContent = "";
  }
}
```

**Примечание:** вы можете найти этот пример на GitHub (также увидеть как он работает.)

Тернарный оператор
------------------

Это последний теоретический раздел данной статьи и мы перейдём к практическим упражнениям. Тернарный или условный оператор имеет простой синтаксис: он проверяет условие и возвращает одно значение или выражение, если условие является `true`, и другое значение/выражение, если условие является `false`. Часто это очень удобная альтернатива блоку `if...else`, позволяющая затрачивать меньшие усилия на написание кода, когда имеется всего лишь два варианта, выбираемых на основе условия `true`/`false`. Общая схема оператора:
```

( условие) ? выполнить этот код : выполнить этот код вместо первого
```

Приведём простой пример:

```js
var greeting = isBirthday
  ? "С днём рождения, г-н Кузнецов! Хорошо вам повеселиться!"
  : "Доброе утро, г-н Кузнецов.";
```

У нас есть переменная `isBirthday` , если она `true`, мы отправляем посетителю поздравление с днём рождения; если нет – выдаём стандартное приветствие.

### Пример тернарного оператора

При использовании тернарного оператора не обязательно ограничиваться лишь значениями переменной, можно выполнять функции или строки кода; все, что угодно. В следующем примере показано простое средство выбора темы, задающее внешний вид веб-сайта с помощью тернарного оператора.

```html
<label for="theme">Выберите тему: </label>
<select id="theme">
  <option value="white">Белая</option>
  <option value="black">Чёрная</option>
</select>

<h1>Это мой веб-сайт</h1>
```

```js
var select = document.querySelector("select");
var html = document.querySelector("html");
document.body.style.padding = "10px";

function update(bgColor, textColor) {
  html.style.backgroundColor = bgColor;
  html.style.color = textColor;
}

select.onchange = function () {
  select.value === "black"
    ? update("black", "white")
    : update("white", "black");
};
```

Мы используем элемент `<select>` для выбора темы (чёрная или белая), а также простой `<h1>` (en-US) для отображения заголовка веб-сайта. Кроме того, у нас есть функция `update()`, принимающая в качестве параметров (входных данных) два цвета. В качестве фона используется первый переданный цвет, а в качестве цвета текста – второй переданный цвет.

Наконец, у нас есть обработчик событий onchange , использующийся для запуска функции, содержащей тернарный оператор. Сначала она проверяет условие — `select.value === 'black'`. Если возвращается `true`, мы запускаем функцию `update()` с параметрами чёрного и белого, в результате чего получаем чёрный цвет фона и белый цвет текста. Если возвращается `false`, мы запускаем функцию `update()` с параметрами белого и чёрного, в результате чего цвета веб-сайта меняются на противоположные.

**Примечание:** вы можете найти этот пример на GitHub (также увидеть как он работает.)

Практическое упражнение: простой календарь
------------------------------------------

В данном примере вы поможете нам закончить простое приложение календаря. Код включает:

* Элемент `<select>`, позволяющий пользователю выбирать разные месяцы.
* Обработчик событий `onchange` для обнаружения изменения значения, выбранного в меню `<select>`.
* Функция `createCalendar()` , рисующая календарь и отображающая правильный месяц в элементе `<h1>` (en-US).

Вы должны написать условную конструкцию в функции обработчика `onchange` , сразу после комментария `// ДОБАВЬТЕ СЮДА УСЛОВНОЕ ВЫРАЖЕНИЕ`. Конструкция должна:

1. Проверить выбранный месяц (хранящийся в переменной `choice`. Это будет значение элемента `<select>` после изменения значения, например, "Январь".)
2. Задать переменную, скажем, `days`, равную количеству дней в выбранном месяце. Для этого нужно будет проверить количество дней в каждом месяце. Високосный год можно не учитывать.

Советы:

* Советуем использовать логический оператор OR для группировки нескольких месяцев в рамках одного условия; многие месяцы имеют одинаковое количество дней.
* Подумайте, какое количество дней в месяце встречается чаще всего и используйте его в качестве варианта по умолчанию.

Если допустили ошибку, используйте кнопку «Сброс», чтобы вернуться к исходному виду примера. Если у вас совсем ничего не получается, нажмите «Показать решение».

**Примечание:** В HTML коде внутри `<select>` названия месяцев `value=""` введены на русском языке. Соответственно ссылки на них из вашего скрипта так же на русском. Не забываем про синтаксис. (прим. - ConstantineZz)
```

<h2>Live output</h2>
<div class="output" style="height: 500px;overflow: auto;">
  <label for="month">Выберите месяц: </label>
  <select id="month">
    <option value="Январь">Январь</option>
    <option value="Февраль">Февраль</option>
    <option value="Март">Март</option>
    <option value="Апрель">Апрель</option>
    <option value="Май">Май</option>
    <option value="Июнь">Июнь</option>
    <option value="Июль">Июль</option>
    <option value="Август">Август</option>
    <option value="Сентябрь">Сентябрь</option>
    <option value="Октябрь">Октябрь</option>
    <option value="Ноябрь">Ноябрь</option>
    <option value="Декабрь">Декабрь</option>
  </select>
  <h1></h1>
  <ul></ul>
</div>

<h2>Editable code</h2>

<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 400px;width: 95%">
var select = document.querySelector('select');
var list = document.querySelector('ul');
var h1 = document.querySelector('h1');

select.onchange = function() {
  var choice = select.value;

  // ДОБАВЬТЕ СЮДА УСЛОВНОЕ ВЫРАЖЕНИЕ

  createCalendar(days, choice);
}

function createCalendar(days, choice) {
  list.innerHTML = '';
  h1.textContent = choice;
  for (var i = 1; i <= days; i++) {
    var listItem = document.createElement('li');
    listItem.textContent = i;
    list.appendChild(listItem);
   }
}

createCalendar(31,'Январь');
</textarea>

<div class="playable-buttons">
  <input id="reset" type="button" value="Сброс" />
  <input id="solution" type="button" value="Показать решение" />
</div>
```

```
.output \* {
  box-sizing: border-box;
}

.output ul {
  padding-left: 0;
}

.output li {
  display: block;
  float: left;
  width: 25%;
  border: 2px solid white;
  padding: 5px;
  height: 40px;
  background-color: #4a2db6;
  color: white;
}

html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background: #f5f9fa;
}
```

```
var textarea = document.getElementById("code");
var reset = document.getElementById("reset");
var solution = document.getElementById("solution");
var code = textarea.value;
var userEntry = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", function () {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Показать решение";
  updateCode();
});

solution.addEventListener("click", function () {
  if (solution.value === "Показать решение") {
    textarea.value = solutionEntry;
    solution.value = "Скрыть решение";
  } else {
    textarea.value = userEntry;
    solution.value = "Показать решение";
  }
  updateCode();
});

var jsSolution =
  "var select = document.querySelector('select');\nvar list = document.querySelector('ul');\nvar h1 = document.querySelector('h1');\n\nselect.onchange = function() {\n var choice = select.value;\n var days = 31;\n if(choice === 'Февраль') {\n days = 28;\n } else if(choice === 'Апрель' || choice === 'Июнь' || choice === 'Сентябрь'|| choice === 'Ноябрь') {\n days = 30;\n }\n\n createCalendar(days, choice);\n}\n\nfunction createCalendar(days, choice) {\n list.innerHTML = '';\n h1.textContent = choice;\n for(var i = 1; i <= days; i++) {\n var listItem = document.createElement('li');\n listItem.textContent = i;\n list.appendChild(listItem);\n }\n }\n\ncreateCalendar(31,'Январь');";
var solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

textarea.onkeydown = function (e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    insertAtCaret("\t");
  }

  if (e.keyCode === 27) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  var scrollPos = textarea.scrollTop;
  var caretPos = textarea.selectionStart;

  var front = textarea.value.substring(0, caretPos);
  var back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );
  textarea.value = front + text + back;
  caretPos = caretPos + text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = function () {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Показать решение") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }

  updateCode();
};
```

Практическое упражнение: расширяем выбор цветов
-----------------------------------------------

В данном примере вы будете использовать пример тернарного оператора, который мы рассматривали ранее, и превратите тернарный оператор в инструкцию switch, что позволит увеличить количество вариантов выбора для простого веб-сайта. Посмотрите на `<select>` — на этот раз он включает не два, а целых пять вариантов тем. Нужно добавить инструкцию switch сразу под комментарием `// ДОБАВЬТЕ ИНСТРУКЦИЮ SWITCH`:

* Она должна принимать переменную `choice` в качестве входного выражения.
* Каждый элемент case должен содержать вариант выбора, соответствующий одному из доступных для выбора значений: белая, чёрная, лиловая, жёлтая или психоделическая тема.
* В блоке каждого элемента case необходимо вызывать функцию `update()`, которой передаётся два цвета: первый – это цвет фона, а второй – цвет текста. Помните, что значения цветов – это строковые значения, поэтому их нужно заключать в кавычки.

Если допустили ошибку, используйте кнопку «Сброс», чтобы вернуться к исходному виду примера. Если у вас совсем ничего не получается, нажмите «Показать решение».
```

<div class="output" style="height: 300px;">
  <label for="theme">Выберите тему: </label>
  <select id="theme">
    <option value="white">Белая</option>
    <option value="black">Чёрная</option>
    <option value="purple">Лиловая</option>
    <option value="yellow">Жёлтая</option>
    <option value="psychedelic">Психоделическая</option>
  </select>

  <h1>Это мой веб-сайт</h1>
</div>

<hr />

<textarea id="code" class="playable-code" style="height: 450px;">
var select = document.querySelector('select');
var html = document.querySelector('.output');

select.onchange = function() {
  var choice = select.value;

  // ДОБАВЬТЕ ИНСТРУКЦИЮ SWITCH
}

function update(bgColor, textColor) {
  html.style.backgroundColor = bgColor;
  html.style.color = textColor;
}</textarea
>

<div class="playable-buttons">
  <input id="reset" type="button" value="Сброс" />
  <input id="solution" type="button" value="Показать решение" />
</div>
```

```
var textarea = document.getElementById("code");
var reset = document.getElementById("reset");
var solution = document.getElementById("solution");
var code = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", function () {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Показать решение";
  updateCode();
});

solution.addEventListener("click", function () {
  if (solution.value === "Показать решение") {
    textarea.value = solutionEntry;
    solution.value = "Скрыть решение";
  } else {
    textarea.value = userEntry;
    solution.value = "Показать решение";
  }
  updateCode();
});

var jsSolution =
  "var select = document.querySelector('select');\nvar html = document.querySelector('.output');\n\nselect.onchange = function() {\n var choice = select.value;\n\n switch(choice) {\n case 'black':\n update('black','white');\n break;\n case 'white':\n update('white','black');\n break;\n case 'purple':\n update('purple','white');\n break;\n case 'yellow':\n update('yellow','darkgray');\n break;\n case 'psychedelic':\n update('lime','purple');\n break;\n }\n}\n\nfunction update(bgColor, textColor) {\n html.style.backgroundColor = bgColor;\n html.style.color = textColor;\n}";
var solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

textarea.onkeydown = function (e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    insertAtCaret("\t");
  }

  if (e.keyCode === 27) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  var scrollPos = textarea.scrollTop;
  var caretPos = textarea.selectionStart;

  var front = textarea.value.substring(0, caretPos);
  var back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );
  textarea.value = front + text + back;
  caretPos = caretPos + text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = function () {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Показать решение") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }

  updateCode();
};
```

Заключение
----------

Это все, что вам нужно знать на данный момент об условных логических структурах! Уверены, вы хорошо разобрались в теоретическом материале и с лёгкостью справились с предложенными упражнениями. Если же что-то осталось для вас непонятным, перечитайте статью ещё раз или свяжитесь с нами.

Смотрите также
--------------

* Comparison operators
* Conditional statements in detail
* if...else reference
* Conditional (ternary) operator reference
* Обзор: Building blocks
* Далее


Массивы - Изучение веб-разработки

Массивы
=======

* Назад
* Обзор: Первые шаги
* Далее

В финальной статье этого раздела, мы познакомимся с массивами — лаконичным способом хранения списка элементов под одним именем. Мы поймём, чем они полезны, затем узнаем, как создать массив, получить, добавить и удалить элементы, хранящиеся в массиве.

| Необходимые навыки: | Базовая компьютерная грамотность, базовое понимание HTML и CSS, понимание о том, что такое JavaScript. |
| --- | --- |
| Цель: | Понять, что такое массивы и как использовать их в JavaScript. |

Что такое массив?
-----------------

Массивы обычно описываются как «объекты, подобные спискам»; они представляют собой в основном отдельные объекты, которые содержат несколько значений, хранящихся в списке. Объекты массива могут храниться в переменных и обрабатываться во многом так же, как и любой другой тип значения, причём разница заключается в том, что мы можем получить доступ к каждому значению внутри списка отдельно и делать супер полезные и эффективные вещи со списком, а также делать то же самое для каждого из значений. Представим, что у нас есть список продуктов и их цены, хранящиеся в массиве, и мы хотим их просмотреть и распечатать на счёте-фактуре, общая сумма всех цен и распечатка общей цены внизу.

Если бы у нас не было массивов, мы должны были бы хранить каждый элемент в отдельной переменной, а затем вызывать код, выполняющий печать и добавляющий отдельно каждый элемент. Написание такого кода займёт намного больше времени, сам код будет менее эффективным и подверженным ошибкам. Если бы у нас было 10 элементов для добавления в счёт-фактуру, это ещё куда ни шло, но как насчёт 100 предметов? Или 1000? Мы вернёмся к этому примеру позже в статье.

Как и в предыдущих статьях, давайте узнаем о реальных основах работы с массивами, введя некоторые примеры в консоль разработчика.

### Создание массива

Массивы создаются из квадратных скобок , которые содержат список элементов, разделённых запятыми.

1. Допустим, мы бы хотели хранить список покупок в массиве — мы бы сделали что-то вроде этого. Введите следующие строчки в вашу консоль:

```js
var shopping = ["bread", "milk", "cheese", "hummus", "noodles"];
shopping;
```

2. В данном случае, каждый элемент в массиве — это строка , но имейте в виду, что вы можете хранить любой элемент в массиве — строку, число, объект, другую переменную, даже другой массив. Вы также можете перемешивать типы элементов — они не должны все быть числами, строками, и так далее. Попробуйте это:

```js
var sequence = [1, 1, 2, 3, 5, 8, 13];
var random = ["tree", 795, [0, 1, 2]];
```

3. Попробуйте сами создать несколько массивов, перед тем как двигаться дальше.
### Получение и изменение элементов массива

Вы можете после этого получать доступ к отдельным элементам в массиве, используя квадратные скобки, таким же способом каким вы получаете доступ к буквам в строке.

1. Введите следующее в вашу консоль:

```js
shopping[0];
// возвращает "bread"
```

2. Вы также можете изменять элемент в массиве, просто дав отдельному элементу массива новое значение. Попробуйте это:

```js
shopping[0] = "tahini";
shopping;
// shopping теперь возвратит [ "tahini", "milk", "cheese", "hummus", "noodles" ]
```

**Примечание:** Мы уже упоминали это прежде, но просто как напоминание — компьютеры начинают считать с нуля!
3. Заметьте, что массив внутри массива называется многомерным массивом. Вы можете получить доступ к элементу внутри массива, который сам находится внутри другого массива, объединив два набора квадратных скобок. Например, для доступа к одному из элементов внутри массива, который является третьим элементом внутри массива `random` (см. предыдущую секцию данной статьи), мы могли бы сделать что-то вроде этого:

```js
random[2][2];
```

4. Попробуйте внести некоторые дополнительные изменения в свои примеры массивов, прежде чем двигаться дальше.
### Нахождение длины массива

Вы можете найти длину массива (количество элементов в нём) точно таким же способом, как вы находите длину строки (в символах) — используя свойство `length`. Попробуйте следующее:

```js
sequence.length;
// должно возвратить 7
```

Это свойство имеет и другие применения, но чаще всего используется, чтобы сказать, что цикл продолжается, пока он не зациклится на всех элементах массива. Так, например:

```js
var sequence = [1, 1, 2, 3, 5, 8, 13];
for (var i = 0; i < sequence.length; i++) {
  console.log(sequence[i]);
}
```

В будущих статьях вы узнаете о циклах, но вкратце этот код говорит:

1. Начать цикл с номера позиции 0 в массиве.
2. Остановить цикл на номере элемента, равном длине массива. Это будет работать для массива любой длины, но в этом случае он остановит цикл на элементе номер 7 (это хорошо, поскольку последний элемент, который мы хотим, чтобы цикл был закрыт, равен 6).
3. Для каждого элемента вернуть его значение в консоли браузера с помощью `console.log()`.
Некоторые полезные методы массивов
----------------------------------

В этом разделе мы рассмотрим некоторые полезные методы, связанные с массивом, которые позволяют нам разбивать строки на элементы массива и наоборот, а также добавлять новые элементы в массивы.

### Преобразование между строками и массивами

Часто у вас могут быть некоторые необработанные данные, содержащиеся в большой длинной строке, и вы можете захотеть разделить полезные пункты до более удобной и полезной формы, а затем сделать что-то для них, например отобразить их в таблице данных. Для этого мы можем использовать метод `split ()`. В его простейшей форме он принимает единственный параметр, символ, который вы хотите отделить в строке, и возвращает подстроки между разделителем как элементы в массиве.

**Примечание:** Хорошо, технически это строковый метод, не метод массива, но мы поместили его в массивы, так как он хорошо подходит для них.

1. Поиграем с этим, посмотрим как это работает. Сначала, создадим строку в вашей консоли:

```js
var myData = "Manchester,London,Liverpool,Birmingham,Leeds,Carlisle";
```

2. Теперь разделим ee посредством запятой:

```js
var myArray = myData.split(",");
myArray;
```

3. Наконец, попробуйте найти длину вашего нового массива и извлечь из него некоторые элементы:

```js
myArray.length;
myArray[0]; // первый элемент в массиве
myArray[1]; // второй элемент в массиве
myArray[myArray.length - 1]; // последний элемент в массиве
```

4. Вы можете сделать обратное используя метод`join()` . Попробуйте следующее:

```js
var myNewString = myArray.join(",");
myNewString;
```

5. Другой способ преобразования массива в строку - использовать метод `toString()`. `toString()`, возможно, проще,чем `join()` поскольку он не принимает параметр, но это ограничивает его. С `join()` вы можете указать разные разделители (попробуйте выполнить шаг 4 с другим символом, кроме запятой).

```js
var dogNames = ["Rocket", "Flash", "Bella", "Slugger"];
dogNames.toString(); //Rocket,Flash,Bella,Slugger
```

### Добавление и удаление элементов массива

Мы ещё не рассмотрели добавление и удаление элементов массива - давайте посмотрим на это сейчас. Мы будем использовать массив `myArray` , с которым мы столкнулись в предыдущем разделе. Если вы ещё не прошли этот раздел, сначала создайте массив в консоли:

```js
var myArray = [
  "Manchester",
  "London",
  "Liverpool",
  "Birmingham",
  "Leeds",
  "Carlisle",
];
```

Прежде всего, чтобы добавить или удалить элемент с конца массива, мы можем использовать `push()` и `pop()` соответственно.

1. Давайте сначала используем метод `push()` — заметьте, что вам нужно указать один или более элементов, которые вы хотите добавить в конец своего массива. Попробуйте это:

```js
myArray.push("Cardiff");
myArray;
myArray.push("Bradford", "Brighton");
myArray;
```

2. При завершении вызова метода возвращается новая длина массива. Если бы вы хотели сохранить новую длину массива в переменной, вы бы могли сделать что-то вроде этого:

```js
var newLength = myArray.push("Bristol");
myArray;
newLength;
```

3. Удаление последнего элемента массива можно совершить с помощью вызова метода `pop()`. Попробуйте это:

```js
myArray.pop();
```

4. Когда вызов метода завершается, возвращается удалённый элемент. Вы бы могли также сделать такое:

```js
var removedItem = myArray.pop();
myArray;
removedItem;
```

`unshift()` и `shift()` работают точно таким же способом, за исключением того что они работают в начале массива, а не в конце.

1. Сначала, попробуем метод `unshift()`:

```js
myArray.unshift("Edinburgh");
myArray;
```

2. Теперь `shift()`; попробуйте эти!

```js
var removedItem = myArray.shift();
myArray;
removedItem;
```

Практика: Печать продуктов!
---------------------------

Вернёмся к описанному выше примеру - распечатываем названия продуктов и цен на счёт-фактуру, затем суммируем цены и печатаем их внизу. В приведённом ниже редактируемом примере есть комментарии, содержащие числа - каждая из этих отметок является местом, где вы должны добавить что-то в код. Они заключаются в следующем:

1. Ниже комментария `// number 1` имеется ряд строк, каждая из которых содержит название продукта и цену, разделённые двоеточием. Нужно превратить их в массив и сохранить его под названием `products`.
2. На строке с комментарием `// number 2` начинается цикл for. В строке цикла имеется `i <= 0`, что является условием , которое заставляет цикл for выполняться только один раз, так как это значение i сообщает циклу: «останавливаться, когда `i` меньше или равен 0», при этом `i` начинается с 0. Нужно заменить `i <= 0` условным тестом, который останавливает цикл, когда `i` перестаёт быть меньше длины массива `products` .
3. Под комментарием `// number 3` мы хотим, чтобы вы написали строку кода, которая разбивает текущий элемент массива (`name:price`) на два отдельных элемента: один содержит только имя, а другой - содержащее только цену. Если не знаете, как это сделать, ещё раз просмотрите статью Полезные строковые методы, а лучше, посмотрите раздел Преобразование между строками и массивами этой статьи.
4. В рамках приведённой выше строки нужно преобразовать цену из строки в число. Если не помните, как это сделать, ознакомьтесь со статьёй строки в JavaScript.
5. В верхней части кода есть переменная с именем `total` , которая содержит значение `0`. Внутри цикла (под комментарием `// number 4`) нужно добавить строку, которая добавляет текущую цену товара к этой сумме на каждой итерации цикла, так чтобы в конце кода была выведена корректная сумма в счёт-фактуре. Для этого вам может понадобится оператор присваивания.
6. Под комментарием `// number 5` нужно изменить строку так, чтобы переменная `itemText` была равна "current item name — $current item price", например "Shoes — $23.99" для каждого случая, чтобы корректная информация для каждого элемента была напечатана в счёте-фактуре. Здесь обычная конкатенация строк, которая должна быть вам знакома.
```

<!-- Не выделяйте тут ничего, не копируйте, не всавляйте!
 Еле починил -->

<h2>Live output</h2>

<div class="output" style="min-height: 150px;">
  <ul></ul>

  <p></p>
</div>

<h2>Editable code</h2>

<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 410px;width: 95%">
var list = document.querySelector('.output ul');
var totalBox = document.querySelector('.output p');
var total = 0;
list.innerHTML = '';
totalBox.textContent = '';
// number 1
                'Underpants:6.99'
                'Socks:5.99'
                'T-shirt:14.99'
                'Trousers:31.99'
                'Shoes:23.99';

for (var i = 0; i <= 0; i++) { // number 2
  // number 3

  // number 4

  // number 5
  itemText = 0;

  var listItem = document.createElement('li');
  listItem.textContent = itemText;
  list.appendChild(listItem);
}

totalBox.textContent = 'Total: $' + total.toFixed(2);
</textarea>

<div class="playable-buttons">
  <input id="reset" type="button" value="Reset" />
  <input id="solution" type="button" value="Show solution" />
</div>
```

```
var textarea = document.getElementById("code");
var reset = document.getElementById("reset");
var solution = document.getElementById("solution");
var code = textarea.value;
var userEntry = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", function () {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Show solution";
  updateCode();
});

solution.addEventListener("click", function () {
  if (solution.value === "Show solution") {
    textarea.value = solutionEntry;
    solution.value = "Hide solution";
  } else {
    textarea.value = userEntry;
    solution.value = "Show solution";
  }
  updateCode();
});

var jsSolution =
  "var list = document.querySelector('.output ul');\nvar totalBox = document.querySelector('.output p');\nvar total = 0;\nlist.innerHTML = '';\ntotalBox.textContent = '';\n\nvar products = ['Underpants:6.99',\n 'Socks:5.99',\n 'T-shirt:14.99',\n 'Trousers:31.99',\n 'Shoes:23.99'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(':');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + ' — $' + price;\n\n var listItem = document.createElement('li');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = 'Total: $' + total.toFixed(2);";
var solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

textarea.onkeydown = function (e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    insertAtCaret("\t");
  }

  if (e.keyCode === 27) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  var scrollPos = textarea.scrollTop;
  var caretPos = textarea.selectionStart;

  var front = textarea.value.substring(0, caretPos);
  var back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );
  textarea.value = front + text + back;
  caretPos = caretPos + text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = function () {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Show solution") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }

  updateCode();
};
```

```
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background-color: #f5f9fa;
}
```

Практика: Топ 5 поисковых запросов
----------------------------------

Хорошим тоном, является использование методов массива, таких как `push ()` и `pop ()` - это когда вы ведёте запись активных элементов в веб-приложении. Например, в анимированной сцене может быть массив объектов, представляющих текущую отображаемую фоновую графику и вам может потребоваться только 50 одновременных отображений по причинам производительности или беспорядка. Когда новые объекты создаются и добавляются в массив, более старые могут быть удалены из массива для поддержания нужного числа.

В этом примере мы собираемся показать гораздо более простое использование - ниже мы даём вам поддельный поисковый сайт с полем поиска. Идея заключается в том, что когда в поле поиска вводятся запросы, в списке отображаются 5 предыдущих поисковых запросов. Когда число терминов превышает 5, последний член начинает удаляться каждый раз, когда новый член добавляется в начало, поэтому всегда отображаются 5 предыдущих терминов.

**Примечание:** В реальном приложении для поиска вы, вероятно, сможете щёлкнуть предыдущие условия поиска, чтобы вернуться к предыдущим поисковым запросам и отобразите фактические результаты поиска! На данный момент мы просто сохраняем его.

Чтобы завершить приложение, вам необходимо:

1. Добавьте строку под комментарием `// number 1`, которая добавляет текущее значение, введённое в ввод поиска, к началу массива. Его можно получить с помощью `searchInput.value`.
2. Добавьте строку под комментарием `// number 2`, которая удаляет значение, находящееся в конце массива.
```

<!-- Здесь тоже ничего не выделяйте, не копируйте, не всавляйте!
 Еле починил -->

<h2>Live output</h2>
<div class="output" style="min-height: 150px;">
  <input type="text" /><button>Search</button>

  <ul></ul>
</div>

<h2>Editable code</h2>

<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 370px; width: 95%">
var list = document.querySelector('.output ul');
var searchInput = document.querySelector('.output input');
var searchBtn = document.querySelector('.output button');

list.innerHTML = '';

var myHistory = [];

searchBtn.onclick = function() {
  // we will only allow a term to be entered if the search input isn't empty
  if (searchInput.value !== '') {
    // number 1

    // empty the list so that we don't display duplicate entries
    // the display is regenerated every time a search term is entered.
    list.innerHTML = '';

    // loop through the array, and display all the search terms in the list
    for (var i = 0; i < myHistory.length; i++) {
      itemText = myHistory[i];
      var listItem = document.createElement('li');
      listItem.textContent = itemText;
      list.appendChild(listItem);
    }

    // If the array length is 5 or more, remove the oldest search term
    if (myHistory.length >= 5) {
      // number 2

    }

    // empty the search input and focus it, ready for the next term to be entered
    searchInput.value = '';
    searchInput.focus();
  }
}
</textarea>

<div class="playable-buttons">
  <input id="reset" type="button" value="Reset" />
  <input id="solution" type="button" value="Show solution" />
</div>
```

```
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background: #f5f9fa;
}
```

```
var textarea = document.getElementById("code");
var reset = document.getElementById("reset");
var solution = document.getElementById("solution");
var code = textarea.value;
var userEntry = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", function () {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Show solution";
  updateCode();
});

solution.addEventListener("click", function () {
  if (solution.value === "Show solution") {
    textarea.value = solutionEntry;
    solution.value = "Hide solution";
  } else {
    textarea.value = userEntry;
    solution.value = "Show solution";
  }
  updateCode();
});

var jsSolution =
  "var list = document.querySelector('.output ul');\nvar searchInput = document.querySelector('.output input');\nvar searchBtn = document.querySelector('.output button');\n\nlist.innerHTML = '';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== '') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = '';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement('li');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = '';\n searchInput.focus();\n }\n}";
var solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

textarea.onkeydown = function (e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    insertAtCaret("\t");
  }

  if (e.keyCode === 27) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  var scrollPos = textarea.scrollTop;
  var caretPos = textarea.selectionStart;

  var front = textarea.value.substring(0, caretPos);
  var back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );
  textarea.value = front + text + back;
  caretPos = caretPos + text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = function () {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Show solution") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }

  updateCode();
};
```

Заключение
----------

Прочитав эту статью, мы уверены, что вы согласитесь, что массивы кажутся довольно полезными; вы увидите, что они появляются повсюду в JavaScript, часто в сочетании с циклами, чтобы делать то же самое для каждого элемента массива. Мы научим вас всем полезным основам, которые нужно знать о циклах в следующем модуле, но пока вы должны себе похлопать и воспользоваться заслуженным перерывом; вы проработали все статьи в этом модуле!

Осталось только выполнить тестовую задачу, которая проверит ваше понимание статей, которые вы прочли до этого момента. Удачи!

Посмотрите также
----------------

* Indexed collections — an advanced level guide to arrays and their cousins, typed arrays.
* `Array` — the `Array` object reference page — for a detailed reference guide to the features discussed in this page, and many more.
* Назад
* Обзор: Первые шаги
* Далее
В этом разделе
--------------

* Что такое JavaScript?
* A first splash into JavaScript
* What went wrong? Troubleshooting JavaScript
* Storing the information you need — Variables
* Basic math in JavaScript — numbers and operators
* Handling text — strings in JavaScript
* Useful string methods
* Массивы
* Assessment: Silly story generator