Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sa2kasov/javascript-reference-guide

Reference Guide of JavaScript, DOM, BOM
https://github.com/sa2kasov/javascript-reference-guide

bom dom javascript javascript-guide javascript-references

Last synced: 1 day ago
JSON representation

Reference Guide of JavaScript, DOM, BOM

Awesome Lists containing this project

README

        


JavaScript Logo

# JavaScript: Справочное руководство

### Содержание

1. [История появления](#история-появления)
1. [Создатель языка о его происхождении](#создатель-языка-о-его-происхождении)
2. [Введение в JavaScript](#введение-в-javascript)
3. [Комментарии](#комментарии)
4. [JavaScript в HTML](#javascript-в-html)
5. [Переменные](#переменные)
1. [let](#let)
2. [const](#const)
3. [var](#var)
6. [Операторы](#операторы)
1. [Арифметические](#арифметические-операторы)
2. [Операторы сравнения](#операторы-сравнения)
3. [Логические операторы](#логические-операторы)
7. [Выражения и инструкции](#выражения-и-инструкции)
8. [Типы данных](#типы-данных)
1. [Логический тип](#логический-тип)
2. [Числа](#числа)
3. [Строки](#строки)
1. [Экранирование символов](#экранирование-символов)
2. [Конкатенация](#конкатенация)
3. [Сравнение строк](#сравнение-строк)
4. [Шаблонные литералы](#шаблонные-литералы)
4. [Манипуляции с типами](#манипуляции-с-типами)
5. [Приведение типов](#приведение-типов)
1. [Таблица преобразования типов](#таблица-преобразования-типов)
9. [Управляющие конструкции](#управляющие-конструкции)
1. [if](#if)
2. [Тернарный оператор](#тернарный-оператор)
3. [switch](#switch)
4. [for](#for)
5. [while](#while)
6. [do..while](#dowhile)
7. [for..in](#forin)
8. [Метки](#Метки)
9. [try..catch..finally](#trycatchfinally)
10. [Функции](#функции)
1. [Области видимости](#области-видимости)
2. [Функция как тип данных](#функция-как-тип-данных)
3. [Свойства функций](#свойства-функций)
4. [Анонимная функция](#анонимная-функция)
5. [Стрелочные функции](#стрелочные-функции)
6. [Замыкания](#замыкания)
7. [Рекурсия](#рекурсия)
7. [Поднятие (Hoisting)](#поднятие-hoisting)
11. [Объекты](#объекты)
1. [Создание объекта](#создание-объекта)
2. [Свойства объекта](#свойства-объекта)
1. [Работа свойствами объекта](#работа-свойствами-объекта)
2. [Перебор свойств объекта](#перебор-свойств-объекта)
3. [Сравнение объектов](#сравнение-объектов)
4. [Создание методов в объекте](#создание-методов-в-объекте)
5. [Методы объекта Object](#методы-объекта-object)
1. [Доступ к свойствам объекта](#доступ-к-свойствам-объекта)
2. [Управление свойствами объекта](#управление-свойствами-объекта)
3. [Прочие методы объекта](#прочие-методы-объекта)
6. [Создание метода из имеющейся функции](#создание-метода-из-имеющейся-функции)
7. [call / apply](#call--apply)
12. [Массивы](#массивы)
1. [Создание и работа с массивами](#создание-и-работа-с-массивами)
2. [Добавление элементов в созданный массив](#добавление-элементов-в-созданный-массив)
3. [Перебор элементов массива](#перебор-элементов-массива)
4. [Удаление элемента массива](#удаление-элемента-массива)
5. [Методы для работы с массивами](#методы-для-работы-с-массивами)
1. [Создание массивов](#создание-массивов)
2. [Доступ к элементам массива](#доступ-к-элементам-массива)
3. [Поиск элементов массива](#поиск-элементов-массива)
4. [Получение строки из массива](#получение-строки-из-массива)
5. [Конкатенация массивов](#конкатенация-массивов)
6. [Получение части массива](#получение-части-массива)
7. [Вставка и удаление в любом месте](#вставка-и-удаление-в-любом-месте)
8. [Сортировка массива](#сортировка-массива)
9. [Работа с началом массива](#работа-с-началом-массива)
10. [Работа с концом массива](#работа-с-концом-массива)
11. [Поиск элементов массива](#поиск-элементов-массива)
12. [Итерация по элементам массива](#итерация-по-элементам-массива)
13. [Сведение массива к одному значению](#сведение-массива-к-одному-значению)
14. [Преобразование массива](#преобразование-массива)
15. [Другие методы массива](#другие-методы-массива)
13. [Встроенные объекты](#встроенные-объекты)
1. [Глобальный объект](#глобальный-объект)
1. [Глобальные свойства](#глобальные-свойства)
2. [Глобальные методы](#глобальные-методы)
3. [Примеры использования](#примеры-использования)
2. [Number](#number)
1. [Свойства](#свойства-number)
2. [Методы](#методы-number)
3. [String](#string)
1. [Свойства](#свойства-string)
2. [Методы](#методы-string)
3. [Примеры](#примеры-string)
4. [Math](#math)
1. [Свойства](#свойства-math)
2. [Методы](#методы-math)
5. [Date](#date)
1. [Создание даты](#создание-даты)
2. [Методы](#методы-date)
6. [RegExp: Регулярные выражения](#регулярные-выражения)
1. [Создание](#создание-regexp)
2. [Специальные последовательности](#специальные-последовательности)
3. [Позиции соответствия](#позиции-соответствия)
4. [Операторы регулярного выражения](#операторы-регулярного-выражения)
5. [Квантификаторы](#квантификаторы)
6. [Методы регулярного выражения](#методы-регулярного-выражения)
7. [Примеры использования](#примеры-regex)
7. [Error](#error)
1. [Инициирование исключения](#инициирование-исключения)
14. [Объектно-ориентированное программирование](#объектно-ориентированное-программирование)
1. [Принципы ООП](#принципы-ооп)
2. [Функция-конструктор](#функция-конструктор)
3. [Прототипы](#прототипы)
4. [Классы](#классы)
15. [BOM (Объектная модель браузера)](#bom-Объектная-модель-браузера)
1. [Свойства и методы объекта Window](#свойства-и-методы-window)
2. [Фреймы](#фреймы)
1. [Работа с окнами](#работа-с-окнами)
3. [navigator](#navigator)
4. [history](#history)
5. [location](#location)
6. [screen](#screen)
16. [Клиентский JavaScript](#клиентский-javascript)
1. [Управление загрузкой скриптов. Атрибуты aync и defer](#управление-загрузкой-скриптов.-атрибуты-aync-и-defer)
17. [DOM (Объектная модель документа)](#dom-объектная-модель-документа)
1. [Свойства](#свойства-document)
2. [Методы](#методы-document)
3. [Типы узлов документа](#типы-узлов-документа)
4. [Связи между DOM-элементами](#связи-между-dom-элементами)
5. [Свойства и методы типов узлов DOM](#свойства-и-методы-типов-узлов-dom)
1. [Node](#node)
2. [Element](#element)
3. [HTMLElement](#htmlelement)
4. [Document](#document)
5. [Примеры свойств и методов](#примеры-свойств-и-методов-узлов-dom)
18. [События](#события)
1. [Обработчики событий](#обработчики-событий)
2. [Объект события](#объект-события)
3. [Отмена действия по умолчанию](#отмена-действия-по-умолчанию)
4. [Распространенные типы событий](#распространенные-типы-событий)

## История появления

Основатель языка, Брендан Айк (англ. Brendan Eich) – программист и создатель языка программирования JavaScript. На момент 2024 года исполнительный директор _Brave Software_. Был нанят в компанию _Netscape_ 4 апреля 1995 года, где была поставлена задача внедрить язык программирования _Scheme_ или что-то похожее в браузер Netscape. Поскольку требования были размыты Айка перевели в группу ответственную за серверные продукты, где он проработал месяц занимаясь улучшением протокола HTTP. В мае разработчик был переброшен обратно, в команду, занимающуюся клиентской частью (браузером), где он немедленно начал разрабатывать концепцию нового языка программирования.

Первоначально язык назывался _LiveScript_ и предназначался как для программирования на стороне клиента, так и для программирования на стороне сервера.

_JavaScript_ изначально был придуман для браузера _Netscape Navigator_. Microsoft первый кто позаимствовал этот язык для своего браузера _Internet Explorer_, добавив в него свои новые возможности. На что Netscape подала в суд в результате чего компания Microsoft выпустила аналог языка _JavaScript_, названный под именем _JScript_. Первым браузером, поддерживающим эту реализацию, был _Internet Explorer 3.0_.

По инициативе компании Netscape была проведена стандартизация языка ассоциацией ECMA. Стандартизированная версия имеет название _ECMAScript_. Первой версии спецификации соответствовал _JavaScript_ версии 1.1. _JavaScript_ после своего появления отличался оригинальностью и настолько понравился, что его начали портировать не только в браузеры, но и в другие среды.

### Создатель языка о его происхождении

Создатель языка JavaScript Brendan Eich [поделился](https://www.jwz.org/blog/2010/10/every-day-i-learn-something-new-and-stupid/) историей происхождения языка и объяснил почему он такой, какой есть:

> JS был обязан «выглядеть как Java», только поменьше, быть эдаким младшим братом-тупицей для Java. Кроме того, он должен был быть написан за 10 дней, а иначе мы бы имели что-то похуже JS.

> что-то вроде PHP, только еще хуже. Его босс Netcsape быстро «зарубил» (в июле 1995, если мне не изменяет память; я сдлелал JS в начале/середине мая), т.к. это был уже третий язык после Java и JS. Было и так трудно обосновать то, что у нас 2 новых языка программирования для web.

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

> Считайте, что JavaScript (пожалуйста, только не «JScript») спас вас от VBScript.

> 10 дней на то, чтобы сделать лексер, парсер, компилятор в байткод (bytecode emitter), интерпретатор, встроенные классы и декомпилятор. Помощь была только с файлом jsdate.c — от Ken Smith из Netscape (который, по нашему излишне оптимистичному соглашению, склонировал java.util.Date — Y2K баги и т.д. Джеймс Гослинг...).

> Простите, времени было мало для того, чтобы сделать правильную оптимизацию хвостовой рекурсии. 10 дней почти без сна, чтобы сделать JS с чистого листа, заставить его «выглядеть как Java» (я сделал, чтобы он выглядел как C), и тайком протащить туда его спасительные фишки: first class functions (замыкания сделал позже, но они были частью плана сразу) и прототипы (примерно как в языке Self).

> I'll do better in the next life.

## Введение в JavaScript

_JavaScript_ – алгоритмический язык программирования, интерпретируемый язык сценариев, основан на синтаксисе _C_ и _Java_.

_JavaScript_ является объектно-ориентированным языком, но используемое в языке прототипирование обуславливает отличия в работе с объектами по сравнению с традиционными класс-ориентированными языками. Кроме того, _JavaScript_ имеет ряд свойств, присущих функциональным языкам: функции как объекты первого класса, объекты как списки, каррирование, анонимные функции, замыкания, ..., что придаёт языку дополнительную гибкость.

**Популярность языка**

_JavaScript_ является самым популярным языком программирования, используемый для frontend-разработки на стороне клиента. Согласно [рейтингу TIOBE Index](https://www.tiobe.com/tiobe-index), базирующемуся на данных поисковых систем Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube и Baidu, на начало 2023 года JavaScript находится на :trophy: 7 месте, постоянно улучшая свои позиции за последние несколько лет. :trophy: 1 место в [рейтинге GitHub](https://octoverse.github.com/#top-languages-over-the-years) 2021 года. :trophy: 7 место в [рейтинге IEEE](https://spectrum.ieee.org/top-programming-languages-2022) (Институт инженеров электротехники и электроники) в 2022 году. По опросам разработчиков на [StackOverflow](https://survey.stackoverflow.co/2022/#section-most-popular-technologies-programming-scripting-and-markup-languages) в 2022 году JavaScript занимает :trophy: 1 место уже 10 лет подряд как самый часто используемый язык программирования.

**Некоторые отличительные особенности JavaScript:**

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

**Нотация – устоявшиеся правила записи**

* Все имена маленькими буквами;
* На стыке слов большая буква (camelStyleNotation);
* Переменные и свойства — существительные;
* Массивы и коллекции — существительные во множественном числе;
* Функции и методы — глаголы;
* Названия классов с Большой буквы.

## Комментарии

Комментарии в JavaScript могут быть строчными – начинаются с `//` и блочными (многострочными) – начинаются с `/*` и заканчиваются с `*/`.

```js
// Однострочный комментарий

/*
Многострочный
комментарий
*/
```

## JavaScript в HTML

JavaScript может быть встроен в код HTML с помощью тега ``. Если подключается внешний файл скриптов, то используется атрибут `src` в котором указывается ссылка на файл скрипта.

```html
<script src="outer.js">
```

Встроенный JavaScript-код заключается между тегами ``. Встроенный JavaScript-код будет игнорироваться если у тега указан атрибут `src`.

```html

// Код на JavaScript

```

## Переменные

- Переменная – именованный участок памяти;
- Переменные объявляются ключевыми словами `let`, `const` и `var`;
- Переменные принимают тот тип данных, который в них присваивается;
- В JavaScript допускается присваивать значение переменной, которая еще не определена, но считается хорошим тоном сначала объявить переменную одним из ключевых слов (пункт 2);
- JavaScript язык с динамической типизацией и переменные являются универсальными для всех типов данных, т.е. способны хранить значения любого типа.

**Объявление и инициализация переменных**

```js
// Объявление переменных
const a
let b, c, d
var e

// Иницилизация переменных
const a = 15
let b = c = d = 50
var e = 'string', f = false, g

// Сокращенная запись
x += 1 // Сокращенная запись x = x + 1
// Доступна и для операторов "+", "-", "*", "/", "%"
i++ // инкремент
i-- // декремент
++i // преинкремент
--i // постдекремент

// Пример
var i = 1
let a = i++ // -> a = 1; i = 2;
let b = ++i // -> b = 3; i = 3;
```

### let

- Имеет блочную область видимости (как и [const](#const));
- Переменная объявляемая как `let` ожидает, что её значение может изменяться;
- Переменные `let` и `const` не участвуют в механизме ["поднятия" (hoisting)](#поднятие-hoisting).

### const

- Переменные `const` (как и [let](#let)) доступны только внутри блока, в котором они были объявлены (например, внутри цикла или условного оператора);
- Главное отличие `const` в том, что значение переменной присваивается один раз и не может быть изменено позже;
- В то же время для сложных типов данных таких как массив или объект допускается изменение содержимого, неизменным остаётся лишь ссылка на эту переменную;
- Использование `const` для любой объявляемой переменной, если её значение не должно изменяться, является хорошей практикой, т.к. явно указывает на константное поведение переменной.

```js
const arr = [1, 2, 3]
arr.push(4)
console.log(arr) // -> [1, 2, 3, 4]
```

### var

- `var` был первым способом объявления переменных в JavaScript, до появления стандарта ECMAScript 6 (ES6) в котором были добавлены `let` и `const`;
- При использовании `var` переменная может быть объявлена повторно без выдачи ошибки;
- Имеют функциональную область видимости (function scope), что означает, что они доступны только внутри функции, в которой они были объявлены;
- Если переменная объявлена внутри блока кода (например, внутри цикла или условного оператора), она все равно будет доступна за пределами этого блока;
- Переменные `var` участвуют в механизме ["поднятия" (hoisting)](#поднятие-hoisting);
- Используйте `var` только в случаях, когда вы знаете, что вам нужна функциональная область видимости, и вам нужно поведение _поднятия (hoisting)_. В остальных случаях рекомендуется использовать `let` и `const`.

## Операторы

### Арифметические операторы

- `+` – плюс
- `-` – минус
- `*` – умножить
- `/` – разделить
- `%` – целочисленный остаток от деления

### Операторы сравнения

- `==` – сравнение
- `===` – сравнение с учетом типа
- `!=` – не равно
- `!==` – не равно с учетом типа
- `>` – больше
- `<` – меньше
- `>=` – больше или равно
- `<=` – меньше или равно

### Логические операторы

_(в порядке приоритета)_
- `!` НЕ (отрицание)
- `&&` И (конъюнкция)
- `||` ИЛИ (дизъюнкция)

```js
1 && 2 // -> 2, значение на котором скрипт остановился
1 && 0 // -> 0
0 && 1 // -> 0, т.к. первый операнд false и нет смысла идти дальше
0 || 'false' // -> "false"
```

Операторы сравнения возвращают булево значение либо `true` либо `false`.

Параметры операторов называются _операндами_. Операторы у которых два операнда называются _бинарными_, один операнд — _унарными_, три — _тернарными_ (только один унарный оператором `!` (логическое "не"));

## Выражения и инструкции

### Выражения

_Expression_

```js
5 + 10
'John'
!false
```

### Инструкции

_Statement_

```js
5 + 10
'John'
!false
```

## Типы данных

_Тип данных_ – набор операций, которые можно выполнить над данными. В JavaScript есть формально 8 типов:

1. Boolean – логический;
2. Number – числовой;
3. BigInt – числа произвольной длины;
4. String – строковый;
5. Array – массив;
6. Object – объект;

Тривиальные типы:

7. undefined – неопределенный тип, любая необъявленная переменная имеет такой тип, а также объявленные переменные, которым еще не присвоено значение или несуществующие свойства объекта;
8. null – отсутствие значения. Если переменная имеет значение _null_, то это означает, что в ней ничего не хранится.

### Логический тип

Может принимать константу `true` или `false`. При проверке значения операндов преобразуются в логический тип.

**Создание**

```js
const b = new Boolean(value) // где value значение для булева типа
```

В JavaScript есть как _Boolean-объекты_, так и примитивные _Boolean_ значения. Не смешивайте их. Объект – это объект. В частности, JavaScript любой объект считается `true`, например при неявном приведении типа в операторе `if`.

```js
const x = new Boolean(false)

if(x) {
// этот код будет выполнен
}
```

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

```js
const x = Boolean(expression) // предпочтительно
const y = new Boolean(expression) // не используйте

// с использованием двойного отрицания:
const z = !!expression
```

На основании «правила лжи» происходит приведение к логическому типу:

* само значение `false`
* `0` или `-0` (число ноль)
* `''` (пустая строка)

Тривиальные типы

* Значение `NULL`
* `undefined`
* `NaN` (Not a Number)

В современном JavaScript-программировании `new Boolean` не используется.

### Числа

**Создание**

```js
// Полня форма
let n = new Number(value) //где value — числовое значение
//Литеральная форма записи
let n = 25
//Приведение к Number
let n = '123'
Number(n) //123
let n = '132A'
Number(n) //NaN
```

В числовой тип входят как целые числа, так и дробные. Экспоненциальные: $5E3$ (пять на 10 в третьей степени).

В JavaScript можно записать числа в 16-ричной или 8-ричной системе счисления, но только с целыми числами. Например, `const y = 0xFF;`. Префиксом числа восьмеричной системой счисления является цифра `0`. Пример: `const z = 040;` будет 32 (в 10-тичной).

**Особые числовые значения**

В тип `Number` входят не только числа, но и еще три значения:

- +бесконечность (`Infinity`);
- -бесконечность (`-Infinity`);
- особое значение `NaN` (Not a Number – значение числового типа не число). Возникает когда вычисление просто не может быть. Например:

```js
const x = 0 / 0 // -> NaN, деление на ноль
const y = Math.sqrt(-1) // -> NaN, отрицательная степень

// Является ли значение числового типа не числом?
isNaN('x' * 10) // -> true

// Является ли значение бесконечным?
isFinite() // false, если значение NaN или ±Infinity, иначе true
```

### Строки

_Строка_ – набор символов, обрамляется в апострофы или двойные кавычки.

#### Экранирование символов

_Экранирование символов_ – вставка специальных символов через знак обратного слэша после которого идет определенный символ.

* `\'` – одинарные кавычки (апостроф);
* `\"` – двойные кавычки;
* `\\` – обратный слэш (`\u005C`);
* `\b` – backspace;
* `\f` – form feed;
* `\n` – переход на новую строку (`\u000A`);
* `\r` – возврат каретки (`\u000D`);
* `\t` – табуляция (`\u0009`);
* `\v` – вертикальная табуляция;
* `\0` – символ NULL (`\u0000`);
* `\ddd` – octal sequence (3 digits: ddd);
* `\xdd` – hexadecimal sequence (2 digits: dd). Символ Latin-1, заданный двумя шестнадцатеричными цифрами;
* `\udddd` – unicode sequence (4 hex digits: dddd). Символ Unicode, заданный четырьмя шестнадцатеричными цифрами.

В JavaScript все хранится в кодировке _Unicode_. Это означает, что мы можем использовать любые символы _Unicode_ прямо в строке (в Юникоде первые 128 символов совпадают с соответствующими символами в ASCII).

```js
// Полное обозначение символа Unicode
const s1 = '\u2014' // Длинное тире (—)
'\u2564' // Денежный знак валюты тенге (₸)

// Шестнадцатеричное
const s2 = '\x20' // Пробел
```

#### Конкатенация

_Конкатенация_ – объединение (сцепление) строк.

```js
"I " + 'am ' + `in ` + "love " + 'with ' + ` JavaScript`
```

#### Сравнение строк

Строки сравниваются в соответствии со своей позицией в Unicode.

```js
'a' > 'A' // -> true
```

#### Шаблонные литералы

Шаблонные литералы (англ. _Template Literals_, неоф. _Template Strings_ или "шаблонные строки") – способ создания строк, позволяющий встраивать переменные и выражения непосредственно в строку, а также писать многострочные строки и теговые шаблоны.

Синтаксис создания таких строк определяется использованием обратных кавычек (англ. _backticks_), для вставки выражений используется конструкция `${выражение}`:

```js
const name = 'John'
let age = 33

console.log(`Hi, My name is ${name}. Next year I'll turn ${age + 1} years old!`)
```

_Шаблонные литералы_ появились в стандарте ECMAScript 2015 (ES6) и призваны обеспечить более удобный и гибкий способ создания строк благодаря лучшей читабельности и простотой работы с динамическими данными по сравнению с традиционными двойными и одинарными кавычками.

Синтаксис создания таких строк определяется использованием обратных кавычек (англ. _backticks_), для вставки выражений используется конструкция `${выражение}`:

```js
const name = 'John'
let age = 33

console.log(`Hi, My name is ${name}. Next year I'll turn ${age + 1} years old!`)
```

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

_Шаблонные литералы_ появились в стандарте ECMAScript 2015 (ES6) и призваны обеспечить более удобный и гибкий способ создания строк благодаря лучшей читабельности и простотой работы с динамическими данными по сравнению с традиционными двойными и одинарными кавычками.

**Многострочный текст**

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

```js
// Создание HTML-кода
const term = 'Template Literals'
const description = 'are literals enclosed by backtick (`` ` ``)'

const html = `


${term}

${description}

`

// Создание SQL-запросов
const id = 123
const sql = `SELECT *
FROM users
WHERE id = ${id}`
```

**Тегированные шаблонные строки**

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

```js
function highlight(strings, nameExp, ...values) {
// Обработка строк и значений
strings[0] // -> "Hello, "
strings[1] // -> "! You're "
strings[2] // -> "years old"
values[0] // -> 32
nameExp // "Jane"
return `${strings[0]}${nameExp} and Welcome${strings[1]}turning ${values[0] + 1}${strings[2]} next year.`
}

let name = 'Jane'
let age = 32
let message = highlight`Hello, ${name}! You're ${age} years old`
console.log(message)
// Hello, Jane and Welcome! You're turning 33 years old next year.
```

**Безопасность**

Использование шаблонных литералов делает код более безопасным, так как автоматически осуществляется экранирование символов. Это помогает предотвратить некоторые виды атак, такие как атаки внедрения SQL.

В шаблонных строках, как и в обычных строках, также можно использовать спецсимволы, такие как перенос строки `\n` или символ возврата каретки `\r`. Над шаблонными строками, как и с обычными, по-прежнему можно использовать встроенные функции JavaScript или методы строк, такие как `.slice()` или `.toLowerCase()`.

### Манипуляции с типами

```js
'2' + '2' // -> строка "22"
2 + '2' // -> строка "22" (строка приоритетнее числа)
'' + true // -> строка "true" (строка приоритетнее булев типа)
2 + true // -> число 3 (число приоритетнее булев типа)
'2' * 10 // -> число 20 (если строка может быть преобразована в число)
'x' * 10 // -> NaN (Not a Namber)

const x = 'x' * 10 // -> NaN
const y = 'y' * 10 //-> NaN
// Однако
x == y // -> false, т.к. NaN != NaN
```

Для проверки типа есть оператор определения типа typeof возвращающая строку соответствующего типа.

```js
typeof 5 // "number"
typeof true // "boolean"
typeof '5' // "string"
```

### Приведение типов

В JavaScript основными преобразованиями типов являются строковые, числовые и логические.

**Преобразование в число**

Числовое значение дают следующие преобразования:

* Умножение строки (которая состоит только из чисел) на число;
* Передать значение как аргумент функции `Number`;
* `parseInt()` – целое число из значения до тех пор, пока не встретится нечисловое значение;
* `parseFloat()` – дробное число из нечислового значения, тоже что и `parseInt()`, но допускается вхождение символа точки.

```js
'5' * 1 // -> целое число 5
'5.5' * 1 // -> дробное число 5.5

parseInt('100.1JS') + 1 // -> целое число 101
parseFloat('10.5JS') // -> дробное число 10.5

Number(true) // -> число 1
Number(false) // -> число 0
```

**Преобразование в строку**

* Строковое преобразование имеет приоритет при попытке сложения двух значений;
* Передача значения как аргумент функции `String`;
* Если в объекте реализован метод `toString()` он будет использован при попытке преобразования объекта в строку.

```js
5 + '' // -> строка '5'
String(true) // -> строка "true"
false + '' // -> строка "false"
```

**Логическое преобразование**

* Логическое сравнение преобразуется для значений при попытке их логического сравнения (`==`, `===`, `&&`, `||` и `!`), в условных конструкциях `if`, `while`, `switch`;
* В логическое значение преобразует функция `Boolean()`.

```js
!!5; // -> true
Boolean(15); // -> true
```

#### Таблица преобразования типов

| Значение | Boolean | Number | String |
|----------------|---------|-----------|-------------------|
| true | true | 1 | "true" |
| false | false | 0 | "false" |
| 0 | false | 0 | "0" |
| 1 | true | 1 | "1" |
| "0" | true | 0 | "0" |
| "1" | true | 1 | "1" |
| NaN | false | NaN | "NaN" |
| Infinity | true | Infinity | "Infinity" |
| -Infinity | true | -Infinity | "-Infinity" |
| "" | false | 0 | "" |
| "строка" | true | NaN | "строка" |
| [ ] | true | 0 | "" |
| { } | true | NaN | "[object Object]" |
| [10] | true | 10 | "10" |
| [10,20] | true | NaN | "10,20" |
| ["строка"] | true | NaN | "строка" |
| ["один","два"] | true | NaN | "один,два" |
| function(){} | true | NaN | "function(){}" |
| null | false | 0 | "null" |
| undefined | false | NaN | "undefined" |

## Управляющие конструкции

### if

Управляющая конструкция `if` выполняет инструкции если условие истинно.

В `if` может быть сколько угодно `else if`. Последнее `else` (без условий) можно опустить, хотя рекомендуется его использовать как «отстойник».

```js
if (condition) {
statement1
statement2
} else if (condition 2) {
statement3
statement4
} else {
statement5
statement6
}
```

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

_Тернарный оператор_ – это оператор с тремя операндами. В JavaScript единственный тернарный оператор это сокращенный вариант записи условной конструкции `if..else..`.

```js
const result

// Обычная условная конструкция
if (условие)
result = 'условие истинно'
else
result = 'условие ложно'

// То же условие через тернарный оператор
b = (a > 1) ? 'условие истинно' : 'условие ложно'
```

Скобки в условии тернарного оператора можно опустить, но для лучшей читаемости не рекомендуется.

### switch

Оператор переключения `switch` позволяет проанализировать множество вариантов значений, используя для анализа числовое или строковое значение.

Внутри конструкции `switch` обычно применяют оператор `break`, т.к. в отсутствии данного оператора если `switch` встретит значение которое соответствует значению в `case`, он выполнить все последующие (нижележащие) инструкции игнорируя все `case` словно их нет.

Оператор `default` сработает если интерпретатор не попадет ни в один `case`.

```js
const a = 2

switch (a) {
case 0:
case 1:
case 2:
console.log('Two')
break;
case 3:
case 4:
case 5:
default:
alert("It's many!")
}
```

### for

Цикл `for` – многократное выполнение одних и тех же действий заранее известное количество раз.

_Итерация_ – однократное выполнение (шаг) цикла.

**Как работает цикл for**

```js
for (часть A; часть B; часть C)
часть D (тело цикла)
```

Когда интерпретатор встречает цикл `for`, он сперва заходит в `часть А` и выполняет то, что там написано ровно один раз. `часть В` выступает как условие, если оно истинно, то интерпретатор заходит в `часть D` (тело цикла), после выполнения которого переходит в `часть С`. Потом возвращается в `часть В` (проверяет условие) и если там истина, то переходит в `часть D` и далее как по треугольнику происходит переход:

> часть В => часть D (тело цикла) => часть С
>
> До тех пор пока часть В не вернет false

Любую из частей цикла for можно опустить, главное чтобы присутствовали точки с запятой как часть синтаксиса.

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

**Цикл for с пустым телом**

Ниже цикл возводит значение переменной `result` в 10-ую степень.

```js
for (let i = 1, result = 2, exp = 10; i < exp; result += result, i++){}
console.log(result) // -> 1024
```

**Цикл for с continue и break**

`continue` в циклах `for`, `while` и `do..while` прерывает текущую итерацию и переход к следующей.

`break` немедленно заканчивает цикл и выходит за операторные скобки.

```js
for (let i = 0; i < 10; i++) {
if (i == 4)
continue

if (i == 8)
break
}
```

### while

* Условие проверяется ПЕРЕД очередным проходом;
* Выполняется пока условие истинно;
* Если условие изначально ложно – не выполнится ни разу.

```js
let num = 1

while (num < 1000) {
num *= 2
if(num == 32) continue
if(num == 512) break
console.log(num)
}
```

### do..while

* Условие проверяется ПОСЛЕ очередного прохода;
* Выполняется пока условие истинно;
* Если условие изначально ложно – выполнится хотя бы один раз.

```js
let num = 1

do {
num *= 2
if (num == 32) continue
else if (num == 512) break
console.log(num)
} while (num < 1000)
```

Если в теле цикла `do..while` все лишь одна инструкция, то операторные скобки можно опустить.

```js
let a = 0
do a++
while (a <= 5) // Одна инструкция в теле цикла
console.log(a) // -> 5
```

### for..in

Предназначен для прохода по массивам, коллекциям, объектам.

```js
for (let prop in navigator) {
console.log(prop)
}
```

### Метки

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

```js
let i = 1

outer: while (i < 10) {
inner: for (let j = 1; j <= i; j++) {
if (j > 2)
continue inner
if (i * j > 10) {
console.log(i, j)
break outer
}
}
i++
} // -> 6, 2
```

### try..catch..finally

`try..catch..finally` – оператор обработки исключений служит для написания кроссбраузерных приложений. Так как при возникновении ошибки в JavaScript исполнение программы останавливается, конструкция `try..catch..finally` позволяет пропустить ошибочную конструкцию и перейти к следующей.

Сначала JavaScript пытается выполнить все что находится в блоке `try`, если внутри блока `try` ошибки не возникнет, то содержимое блока `catch` игнорируется.

Содержимое блока `finally` выполняется при любом случае, вне зависимости от того возникла ошибка или нет.

Разница между кодом в блоке `finally` и кодом в блоке всей этой конструкции проявляется в JavaScript только в случае если в блоке `catch` произойдет ошибка.

В случае возникновения ошибки в `catch` программа остановится за исключением если есть блок `finally`. В таком случае блок `finally` выполнится, а все что после него нет.

Допускается вкладывать конструкции `try..catch..finally` внутри друг друга.

```js
try {
console.log('До ошибки в блоке try')
throw new Error() // В случае ошибки попадаем в блок catch
console.log('После ошибки в блоке try')
} catch(e) { // В переменную "e" заносится информация об ошибке
console.log('Сообщение об ошибке: ' + e.message)
} finally {
console.log('Сообщение из блока «finally»')
}

console.log('Сообщение после конструкции try..catch..finally')
```

## Функции

_Функция_ – некоторый именованный набор кода, который определяется один раз и может вызываться многократно.

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

```js
function sayHello(name) { // Формальные параметры
if (name == null)
name = 'Stranger'
console.log('Hello, ' + name)
}

sayHello('John') // -> Hello, John
sayHello('Jane') // -> Hello, Jane
sayHello() // -> Hello, Stranger
```

### Области видимости

* Глобальные переменные объявляются до описания функций, объявляются вне тела функции и могут быть причиной сложно находимых ошибок;
* Локальные переменные явно объявляются в теле функции и аргументы функции всегда локальные переменные;
* У каждой функции своя область видимости;
* Локальные переменные «живут» столько сколько живет функция.

В примере ниже в функции `foo()` произойдёт перезапись глобальной переменной `x`. В функции же `bar()` с использованием ключевых слов `var`, `let`, `const`.

```js
var x = 'x-global'

function foo () {
x = 'x-local-foo'
return x // Возвратит глобальную переменную "x"
}

foo() // -> x-local-foo

function bar () {
var x = 'x-local-bar'
return x // Возвратит локальную переменную "x"
}

bar() // -> x-local-bar
```

Скорее правильней считать переменные не как глобальные или локальные, а в контексте вложенных функций, как родитель-ребенок. В примере ниже вызов переменной `x` в функции `inner()` произойдет из глобальной области видимости, т.к. переменная `x` не продекларирована внутри самой функции `inner()` и её родительской функции `outer()`. Вызов переменной `y` произойдет из родительской функции `outer()`, что касается переменной `z`, то она передается как аргумент функции `inner()`, что сама по себе является локальной.

```js
function echo (str) {
console.log(str.toString())
}

let x = 'x-global', y = 'y-global', z = 'z-global'

function outer() {
let y = 'y-local'
function inner(z) {
echo(x) // -> x-global
echo(y) // -> y-local
echo(z) // -> z-local
return 'inner function'
}
return inner('z-local')
}

outer() // -> inner function
```

В этом примере нельзя вызвать функцию `inner()` из глобальной области видимости. Она может быть вызвана только внутри функции родителя — `outer()`.

**Засада с областью видимости**

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

```js
var x = 100

function foo(x) {
if(x)
x = 10
else
var x = 20
}

foo(true)
console.log(x) // -> 100
```
Но при выполнении кода мы получим значение `100`, т.к. JavaScript перед исполнением кода, помимо синтаксической проверки также исправляет код и выполнит его так, как если бы он выглядел следующим образом:

```js
var x = 100

function foo(x) {
var x
if (x)
x = 10 // это и
else
x = 20 // это относится к локальной области видимости
}

foo(true)
console.log(x) // -> 100
```

### Функция как тип данных

Функция в JavaScript является таким же типом данных, как Boolean, String, Number, Object, ... Это значит, что с функциями можно производить такие же действия, как и с обычными типами.

```js
function echo(str) {
console.log(str.toString())
}

let print = echo
print('Теперь «print» это точная копия функции «echo»')
```

### Свойства функций

`имя_функции.length` – возвратит количество ожидаемых параметров функции.

```js
function foo(arg1, arg2, arg3) {}
// Сколько параметров ожидает функция?
console.log(foo.length); // -> 3
```

При создании функции автоматически создается объект `arguments`. Свойство `arguments.length` возвращает количество фактически переданных параметров.

```js
function getArgs() {
return arguments.length
}

getArgs(1, 2, 3, 4, 5, 6, 7, 8, 9) // -> 9
```

Все переданные параметры функции доступны в объекте `arguments` каждый под своим порядковым номером начиная с нуля.

```js
function sum() {
let i = result = 0
while (arguments[i]) {
result += arguments[i]
i++
}
return result
}

console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9)) // -> 45
```

### Анонимная функция

_Анонимная функция_ – функция, объявляемая без определённого имени, который мог бы служить идентификатором для доступа к ней. В примере ниже анонимная функция присваивается переменной `sum` после чего, `sum()` становится функцией.

```js
const sum = function(val) {
return val + val;
}

sum(5) // -> 10
```

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

В коде ниже вызов функции `foo()` не вызовет ошибку, в то время как вызов `bar()` выдаст ошибку:

```console
TypeError: bar is not a function
```
Так как на момент выполнения скрипта функция `bar()` не была создана, а появилась только как результат выражения присваивания переменной.

```js
foo()
bar() // -> TypeError: bar is not a function

const bar = function(args) {
statements
}

function foo(parameters) {
statements
}
```

### Стрелочные функции

Стрелочные функции предоставляют более краткую форму записи функций.

```js
// Стандартная функция
function sum(a, b) {
return a + b
}

// Стрелочная функция
const add = (a, b) => a + b
```

**Особенности стрелочных функций**

* Если функция принимает только один параметр, скобки вокруг параметров можно опустить;
* Если тело функции состоит из одного выражения, то его не обязательно заключать в фигурные скобки, а оператор `return` можно также опустить;
* Стрелочные функции не создают собственный контекст `this`, вместо этого они заимствуют контекст от родительской области видимости;
* Стрелочные функции не могут быть использованы с оператором `new` для создания экземпляров объектов;
* Стрелочные функции не имеют доступа к объекту `arguments`.

### Замыкания

_Замыкания_ – способность функции захватывать переменные родительского контекста.

```js
function makeAdd(base) {
return function(num) {
return num + base;
}
}

const addTen = makeAdd(5)
addTen(10) // -> 15
```

**Пример со сравнением чисел**

При первом вызове `compare(10)` функция возвратит внутреннюю функцию при этом сохранив в переменной `x` значение `10`.

```js
function compare(x) {
return function innerCompare(y) {
if (x === y) return null
return x < y
}
}

const checkNum = compare(10) // -> function "innerCompare"
checkNum(9) // -> false
checkNum(10) // -> null
checkNum(11) // -> true
```

### Рекурсия

_Рекурсия_ – вызов функции саму себя. Нахождение факториала числа наиболее распространённый пример рекурсивного вызова функции.

```js
function factorial(n) {
if(n === 0) return 1
return n * factorial(n - 1)
}

factorial(5) // -> 120
```

### Поднятие (Hoisting)

Под поднятием (hoisting) в JavaScript называют механизм поднятия в начало кода объявленных переменных и функций, чтобы они могли быть использованы до своего фактического объявления в коде.

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

Здесь следует уточнить, что "поднимаются" только объявления, но не инициализация (присваивание значений).

**Поднятие функций**

Функция `hi()` исполняется без ошибок невзирая на позднее объявление:

```js
hi() // -> "Greetings"

function hi() {
return "Greetings"
}
```

**Поднятие имён переменных**

Одно из отличий `var` перед `let` и `const` в том, что последние имеют блочную область видимости:

```js
console.log(x) // -> undefined
var x = 1

console.log(y) // -> ReferenceError:
// Cannot access 'y' before initialization
const y = 2
```

## Объекты

* Объектный тип данных – входят все объекты JavaScript (свойства, методы);
* Объект – коллекция данных (свойств), функций (методов), и, возможно, других объектов;
* Объект явно создается с помощью оператора `new`, литерала объекта `{}` или метода `Object.create()`;
* Объект явно уничтожается при уничтожении переменной или присваивании переменной значения `null`;
* Когда мы присваиваем значение некоему свойству объекта, которого нет в объекте, происходит создание свойства;
* В JavaScript почти всё является объектом. Даже примитивные типы данных при необходимости могут "упаковываться" в объекты-обёртки. Например, `const x = 17.5` эквивалентно `const x = new Number(17.5)`.

### Создание объекта

```js
// Создание объекта с помощью конструктора Object()
let Book = new Object()

// Сокращённая запись с помощью литерала объекта
let User = {
say() {
console.log('Hello!')
}
}

// Создание объекта с методом Object.create() на основе прототипа (User)
const John = Object.create(User)
John.say() // -> "Hello!"

// Создание свойств
Book.title = 'JavaScript. Подробное руководство' // String
Book['author'] = 'Дэвид Флэнаган' // Имя как ключ массива
Book.year = 2021 // Number значение
Book.isAvailable = true // Boolean значение
Book.order() // вызов метода

// Недопустимая форма записи
obj.word1-word2 = true // -> Ошибка, SyntaxError
obj.'property' = true // -> Ошибка, SyntaxError
```

Другие способы создания объекта с помощью функции-конструктора и синтаксиса классов рассмотрены далее в разделе [Объектно-ориентированное программирование](##объектно-ориентированное-программирование).

### Свойства объекта

Если имя свойства содержит символы недопустимые в названии переменной (пробелы, дефисы) или оно совпадает с зарезервированным словом (например: `var`, `for`, `instanceof`, ...), то необходимо имя свойства заключить в кавычки. В этом случае обращаться к свойству нужно с помощью квадратных скобок. Например, `objName['object\'s property']`.

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

```js
const Car = {
speed: 220,
color: 'orange',
'year': 2025,
'sport car': false
}

const Audi = Car // копия объектв
Audi['car-body'] = 'coupe'
```

#### Работа со свойствами объекта

Методы для работы со свойствами объекта рассмотрены в разделе [Управление свойствами объекта](#управление-свойствами-объекта)

_Удаление свойства объекта_

```js
delete Audi['car-body']
delete Audi.color
```

_Проверка на наличие свойств в объекте_

```js
'color' in Audi // -> false
'sport car' in Audi // -> true
```

_Динамическое обращение к свойствам объекта_

Названия свойств могут формироваться динамически путём результата выражения.

```js
const User = {
isAdmin: 'yes',
'2': 0
}

console.log(User[1 + 1]) // -> 0, обращение к свойству '2'
const x = 'is'
console.log(User[x + 'Admin']) // -> "yes"
```

#### Перебор свойств объекта

В принципе, если бы названия свойств объекта состояли только из чисел, то можно было бы воспользоваться циклом `for`. Например:

```js
const NumberObject = {
1 : 'свойство 1',
2 : 'свойство 2',
3 : 'свойство 3',
4 : 'свойство 4',
}

for (let i = 1; i in NumberObject; i++) {
console.log(NumberObject[i])
}
```

Для прохода по объектам или коллекциям используется конструкция `for..in`.

```js
const AssocObj = {
0 : 'male',
age : 21,
'name' : 'John',
true : false
}

for (let current in AssocObj) { // где current – имя свойства
console.log(current + ': ' + AssocObj[current])
}
```

### Сравнение объектов

При присваивании переменной, которая хранит в себе объект происходит ссылка на этот самый объект. И при сравнении двух переменных возвратится значение `true` не по причине одинакового содержимого двух объектов, а потому, что обе переменные являются ссылкой на один и тот же объект. Так, в примере ниже объект `o1` возвратит `true` при сравнении с объектом `o2`. И все дальнейшие изменения с объектов `o2` отобразятся и на объекте `o1`.

В то же время, несмотря на одинаковое содержимое объектов `o1` и `o3` они возвратят `false` при сравнении, т.к. с точки зрения ООП это разные объекты.

```js
const o1 = { x: 150 }
const o2 = o1 // -> ссылка на объект o1
const o3 = { x: 150 }

console.log(o1 == o2) // -> true
console.log(o1 == o3) // -> false

// Измение значение свойства "x" объекта "o2"
o2.x = 200
// Значение свойства "x" объекта "o1" также изменилось
console.log(o1.x)
```

### Создание методов в объекте

Методы создаются путем присваивания анонимной функции.

```js
const Methods = {
one: function() {
console.log('This is method "one"')
},
two: function(param) {
console.log('I am a ' + param)
}
}

methods.one() // -> This is method "one"
methods.two('JavaScript Student') // -> I am a JavaScript Student
```

**Ключевое слово `this`?**

Ключевое слово `this` используется в объектах для передачи ссылки на объект внутри которого он вызывается. Вместо `this` сработало бы и имя объекта, но принято использовать именно `this`.

```js
const MyObject = {
property: 'property value',
method: function() {
console.log(this.property)
},
}

MyObject.method() // -> "property value"
```

### Методы объекта Object

#### Доступ к свойствам объекта

* `Object.keys(obj)` – возвращает массив ключей объекта.

```js
const person = {
name: 'John',
age: 32,
city: 'Almaty'
}

const keys = Object.keys(person)
console.log(keys) // -> ["name", "age", "city"]
```

* `Object.values(obj)` – возвращает массив значений объекта.

```js
const person = {
name: 'Jane',
age: 31,
city: 'Astana'
}

const values = Object.values(person)
console.log(values) // -> ["Jane", 31, "Astana"]
```

* `Object.entries(obj)` – возвращает массив пар "ключ-значение" объекта.

```js
const person = {
name: 'John',
age: 32,
city: 'Shymkent'
}

const entries = Object.entries(person)
console.log(entries) // -> [["name", "John"], ["age", 33], ["city", "Shymkent"]]
```

* `hasOwnProperty(prop)` – проверяет, принадлежит ли свойство непосредственно объекту.

```js
const person = {
name: 'Jane',
age: 31
}

console.log(person.hasOwnProperty('name')) // -> true
console.log(person.hasOwnProperty('toString')) // -> false
```

* `valueOf()` – возвращает примитивное значение объектов Number, Boolean, ...

```js
const n = new Number(5)
n.valueOf() // -> 5

const obj = {
name: 'John',
age: 32,
valueOf: function() {
return this.age;
}
}

console.log(obj + 10) // -> 42 (valueOf() преобразует объект в число)
```

* `имяОбъекта.hasOwnProperty(имяСвойства)` – является ли свойство/метод унаследованным.

```js
const user = {
id: 123,
login: 'Jane',
password: '******',
}

console.log(user.hasOwnProperty('login')) // -> true
console.log(user.hasOwnProperty('toString')) // -> false (унаследовано от прототипа)

Object.prototype.myProperty = 'myValue'

// Напечатает только собственные свойства и методы
for (let i in user) {
if (user.hasOwnProperty(i)) {
console.log(user[i])
}
} // -> 123, Jane, ******
```

* `имяОбъекта.propertyIsEnumerable(имяСвойства)` – является ли свойство перечисляемым.

```js
const user = {
name: "John"
}

Object.defineProperty(user, 'age', {
value: 32,
enumerable: false
})

console.log(user.propertyIsEnumerable('name')) // -> true
console.log(user.propertyIsEnumerable('age')) // -> false (свойство не перечисляемое)
```

* `Object.prototype.isPrototypeOf(объект)` – является ли прототип прототипом объекта.

```js
const proto = {
greet: function() {
console.log('Hello! World')
}
}

const obj = Object.create(proto)

console.log(proto.isPrototypeOf(obj)) // -> true
```

#### Управление свойствами объекта

* `Object.defineProperty(obj, prop, descriptor)` – определяет новое свойство или изменяет существующее.

```js
const person = {}

Object.defineProperty(person, 'name', {
value: 'John',
writable: false, // Нельзя изменить значение
enumerable: true, // Можно перечислить свойство
configurable: false // Нельзя удалить или изменить конфигурацию свойства
})

console.log(person.name) // -> "John"

person.name = 'Jane' // Ошибка, свойство name не перезаписывается
```

* `Object.defineProperties(obj, props)` – определяет несколько свойств.

```js
const person = {}

Object.defineProperties(person, {
name: {
value: 'John',
writable: false
},
age: {
value: 32,
writable: true
}
})

console.log(person.name) // -> "John"
console.log(person.age) // -> 32

person.age = 33 // Изменение значения свойства age
console.log(person.age) // 33
```

* `delete obj.prop` – удаляет свойство из объекта.

```js
const person = {
name: 'John',
age: 32
}

delete person.age

console.log(person.name) // "John"
console.log(person.age) // undefined
```

#### Прочие методы объекта

* `Object.assign(target, ...sources)` – копирует свойства из исходных объектов в целевой объект.

```js
const target = { name: 'John' }
const source1 = { age: 32 }
const source2 = { city: 'Almaty' }

Object.assign(target, source1, source2)
console.log(target) // -> { name: 'John', age: 32, city: "Almaty" }
```

* `Object.freeze(obj)` – делает объект неизменяемым.

```js
const user = {
name: 'Jane',
age: 31
}

Object.freeze(user)
user.age = 30 // -> false
console.log(user) // { name: "Jane", ag }
```

* `Object.seal(obj)` – запрещает добавление новых свойств, но разрешает изменение существующих.

```js
const user = {
name: 'John',
age: 32
}

Object.seal(user)
user.age = 31 // Свойство "age" будет изменено
user.sex = 'male' // Свойство "sex" не будет добавлено
delete user.name // Свойство "name" не будет удалено

console.log(user) // -> { name: "John", age: 32 }
```

* `Object.is(value1, value2)` – определяет, являются ли два значения одинаковыми.

```js
console.log(Object.is(10, 10)) // -> true
console.log(Object.is('hello', 'world')) // -> false
console.log(Object.is(NaN, NaN)) // -> true
console.log(Object.is(0, -0)) // -> false
```

### Создание метода из имеющейся функции

```js
function foo() {
console.log(this.name)
}

const users = {
name: 'John',
getName: foo, // Присваивание имеющейся функции
}

users.getUserName = foo // Присваивание имеющейся функции
users.getName() // -> John
```

### call / apply

Любую функцию в JavaScript можно вызывать в контексте любого объекта. Это нужно когда нет необходимости громоздить объект лишними функциями. Для этого есть методы `call` и `apply`. Метод `apply` очень похож на `call`, за исключением передачи аргументов. В `apply` используется массив аргументов вместо списка именованных параметров.

```js
function outer(x, y) {
return this.num + x + y
}

const ObjectOne = {
num: 10,
}

// Первый аргумент задает значение this внутри функции
outer.call(ObjectOne, 50, 190); // -> 250

// Вызов функции внутри объекта
const ObjectTwo = {
num: 15,
method: function() {
return outer.apply(this, [12, 8])
},
}

ObjectTwo.method() // -> 35
```

## Массивы

* Массив – упорядоченный набор данных;
* Доступ к элементам массива осуществляется по его номеру (индексу);
* Элементы массива нумеруются с нуля.

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

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

```js
// С помощью литерала
let arr = [] // Иницилизация пустого массива
arr = ['string', 1, true]
typeof arr // -> "object" (массив это Объект)

// С помощью конструктора Array
let arr2 = new Array(5) // -> [undefined × 5]
arr2 = new Array(5, 10, 15, 20, 25, 30)

// Заполнение уже созданного массива
arr['name'] = 'John'
arr['surname'] = 'Doe'
arr.age = 30

// Создадим пару функций для последующего добавления их в массив
function sayHello() {
return 'Hello! World'
}

const multiple = function() {
let result = 1, i = 0

do {
result *= arguments[i]
i++
} while(arguments[i])

return result
}

// Добавление данных при иницилизации массива
const user = [30, 'male', sayHello, multiple, true]

// Обращение к элементам массива
user[0] // -> 30
user[2]() // -> "Hello! World", произошел вызов функции «sayHello»
user[3](2, 2, 4, 2, 5, 3, 10) // -> 4800, вызов функции «multiple»
```

### Добавление элементов в созданный массив

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

> _Индекс последнего элемента массива на единицу меньше длины массива_

Инициализируемый массив `myArray` имеет длину `length = 3`, т.к. последний занятый индекс 2.

После присваивания значения ячейке массива с индексом `10`, в массиве `myArray` хранятся 11 элементов. Элементы с порядковым номером с 4 по 9 имеют значение `undefined`.

```js
const myArray = [0, false, '25']
myArray[myArray.length] = 'еще один элемент в массиве'
console.log(myArray[3]) // -> "еще один элемент в массиве"

// Длина массива
myArray.length // -> 4
myArray[10] = 'x'
myArray.length // -> 11
myArray // [0, false, '25',
// 'еще один элемент в массиве', undefined × 4, 'x']
```

Свойство `length` у массивов доступны не только на чтение, но и на запись. Таким же образом можно сократить количество элементов в массиве.

```js
myArray.length = 3
myArray // -> [0, false, '25']
```

### Перебор элементов массива

```js
const array = ['Jane', 36, true]
array.length = 2 // Сокращение массива (3-ий элемент будет удален)
array[7] = 'z'

for(let i = 0; i < array.length; i++) {
console.log(i + ': ' + array[i])
/* Напечатает:
0: Jane
1: 36
2-6: undefined (x5)
7: z
*/
}

for(let j in array) {
console.log(j + ': ' + array[j])
/* Напечатает:
0: John
1: 25
7: z
*/
}
```

Цикл `for..in` чаще всего оказывается наиболее предпочтительным. В примере выше он опустил все элементы со значением `undefined`, однако он выведет элемент со значением `undefined` если таковой был присвоен явно, например, `array[25] = undefined`.

При удалении элемента массива, индекс массива принимает значение `undefined`. Причем есть разница от `undefined` который произошел в результате удаления и явно присваиваемого `undefined`. В первом случае, значение `undefined` рассматривается как неизвестное(неопределенное) значение, во втором случае, как конкретное значение типа `undefined`.

### Удаление элемента массива

```js
delete array[2]
array // ["Jane", 36, undefined]
array[array.length] = undefined
array // ["Jane", 36, undefined, undefined]
```

### Методы для работы с массивами

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

* `Array.from()` – создает новый массив из итерируемого объекта или псевдомассива.

```js
// Массив из строки
Array.from('hello') // -> ["h", "e", "l", "l", "o"]

// Массив из NodeList
let paragraphs = document.querySelectorAll('p')
Array.from(paragraphs) // -> массив элементов

// Создание массива с преобразованием элементов
let numbers = [1, 2, 3]
Array.from(numbers, n => n * 2) // -> [2, 4, 6]
```

* `Array.fromAsync()` – создает новый массив из асинхронного итерируемого объекта.

```js
async function getFiles() {
let dir = await openDir('.')
let files = []
for await (let file of dir) {
files.push(file)
}
return files
}

let filesArr = await Array.fromAsync(getFiles()) // -> массив файлов в директории
```

* `Array.of()` – создает новый массив из переданных аргументов.

```js
Array.of('Hi', true, 3, [4], {5: 6}) // -> ['Hi', true, 3, [4], {5: 6}]
```

#### Доступ к элементам массива

* `at()` – возвращает элемент массива по заданному индексу.

```js
// Получение первого элемента
let arr = [1, 2, 3]
let firstElement = arr.at(0) // -> 1

// Получение последнего элемента
let arr = [1, 2, 3]
let lastElement = arr.at(-1) // -> 3
```

* `entries()` – возвращает итератор, который содержит пары `[ключ, значение]` для каждого элемента массива.

```js
let arr = ['a', 'b', 'c']
for (let [index, value] of arr.entries()) {
console.log(index, value)
}
// Напечатает:
// 0 "a"
// 1 "b"
// 2 "c"
```

* `keys()` – возвращает итератор, который содержит ключи (индексы) элементов массива.

```js
let arr = ['a', 'b', 'c']
for (let key of arr.keys()) {
console.log(key)
}
// Напечатает:
// 0
// 1
// 2
```

* `values()` – возвращает итератор, который содержит значения элементов массива.

```js
let arr = ['a', 'b', 'c']
for (let value of arr.values()) {
console.log(value)
}
// Напечатает:
// "a"
// "b"
// "c"
```

#### Поиск элементов массива

* `every()` – проверяет, удовлетворяют ли все элементы массива заданному условию.

```js
const numbers = [1, 2, 3, 4, 5]
const allPositive = numbers.every(number => number > 0) // -> true
const allEven = numbers.every(number => number % 2 === 0) // -> false
```

* `filter()` – создает новый массив с элементами, которые прошли проверку заданным условием.

```js
const numbers = [1, 2, 3, 4, 5]
const evenNumbers = numbers.filter(number => number % 2 === 0) // -> [2, 4]
```

* `findLast()` – возвращает последний элемент массива, который удовлетворяет заданному условию.

```js
const numbers = [1, 2, 3, 4, 5]
const lastEvenNumber = numbers.findLast(number => number % 2 === 0) // -> 4
```

* `findLastIndex()` – возвращает индекс последнего элемента массива, который удовлетворяет заданному условию.

```js
const numbers = [1, 2, 3, 4, 5]
const lastEvenNumberIndex = numbers.findLastIndex(number => number % 2 === 0) // -> 3
```

* `some()` – проверяет, удовлетворяет ли хотя бы один элемент массива заданному условию.

```js
const numbers = [1, 2, 3, 4, 5]
const hasEvenNumber = numbers.some(number => number % 2 === 0) // -> true
const allNegative = numbers.some(number => number < 0) // -> false
```

#### Получение строки из массива

* `toString()` – приводит к строке массив, разделяя элементы запятыми;
* `join()` – делает то же самое, что и toString() за тем исключением, что в join() в качестве параметра можно передать разделитель.

```js
const foo = () => 'Hello! World'
const bar = [20, 2, 25, foo]
const baz = bar.toString()
const qux = bar.join(' • ')

console.log(baz) // -> "20,2,25,() => 'Hello! World'"
console.log(qux) // -> "20 • 2 • 25 • () => 'Hello! World'"
```

#### Конкатенация массивов

* `concat()` – возвращает новый массив в котором объеденины все перечисленные через запятую параметры. При этом исходный массив остаётся неизменным.

```js
const foo = [1, 2]
const foo = [3, 4]
foo.concat(foo, 5, 6) // -> [1, 2, 3, 4, 5, 6]
foo // -> 1, 2; Массив foo остается неизменным
```

Оператор `+` в контексте массива приводит каждый массив к строке.

```js
const bar = [1, 2] + [3, 4] // -> "1,23,4"
```

#### Получение части массива

* `slice()` – вырезает часть массива. Функция `slice` не изменяет массив на котором вызывается эта функция, а в качестве результата возвращает копию массива.

В функциях для получения части массива (функции `slice`, `splice`) первый параметр (или если передается только один параметр) отсчет позиции начинается с нуля, если передается отрицательное значение, то отсчет начинается с конца и с единицы.

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

```js
const array = [23, 11, 5, 16, 98, 55]

array.slice(3) // -> 16, 98, 55
```

Можно передать отрицательное значение, тогда отсчет элементов массива начнется с конца.

```js
array.slice(-2) // -> 98, 55
```

Вернется часть массива с позиции первого параметра до позиции второго параметра. Отсчет позиции второго параметра начинается сначала.

```js
array.slice(2, 4) // -> 5, 16
```

В случае передачи неверных данных возвратится пустой массив.

```js
array.slice(5, 2) // -> []
```

#### Вставка и удаление в любом месте

* `splice()` – вырезает или вставляет элементы в массив.

_С одним параметром_. Если передается один параметр, то возвратится часть массива начиная с начала и длиной переданного параметра. Отсчет начинается с единицы.

```js
const array = [14, 22, 'third', true, ['array']]
array.splice(3) // -> ["14, 22, third"]
```

_С двумя параметрами_. Если передается два параметра, то возвратится часть массива начиная с позиции первого параметра и длиной второго параметра.

```js
array = [14, 22, 'third', true, ['array']]
const third = array.splice(2, 1) // -> ["third"]
array // -> ["14, 22, true, array"]
```

_С тремя параметрами_. Если передается три и более параметра, то произойдет вставка всех элементов, переданные третьим (и более если есть) параметром(ов). Первый параметр означает перед каким элементом массива произойдет вставка, второй параметр – количество элементов, которые необходимо вырезать.

```js
const sourceArray = ['1st', '2nd', '4th', '5th']
sourceArray.splice(2, 0, '3rd') // -> ["1st", "2nd", "4th", "5th"]
sourceArray.join() // -> ["1st,2nd,3rd,4th,5th"]
```

Функции `slice()` и `splice()` отличаются тем, что в функции `splice()` второй параметр отсчитывается не с начала массива, а с позиции равной первому параметру. Также в функции `splice()` можно передать три и более параметра. В этом случае происходит вставка новых элементов в массив.

#### Сортировка массива

* `revers()` – реверс массива, функция ничего не возвращает и применяется непосредственно к самому массиву.

```js
const array = [23, 11, 5, 16, 98, 55]
array.reverse() // -> 55, 98, 16, 5, 11, 23
```

* `sort()` – сортирует массив как строки (даже если массив имеет только числовые значения). Функция `sort()` может принимать необязательный параметр — имя функции. Если функция указана, то элементы массива будут отсортированы согласно значениям, возвращаемых функцией. Если параметр не указан, массив будет отсортирован в лексикографическом порядке (возрастающий порядок следования символов в таблице ASCII).

```js
const array = [23, 11, 5, 16, 98, 55]
array.sort() // -> 11, 16, 23, 5, 55, 98

// sort(функция_сортировки)
const mySort = (a, b) => a - b
array.sort(mySort) // -> 5, 11, 16, 23, 55, 98
```

#### Работа с началом массива

* `shift()` – извлекает и возвращает первый элемент массива. Исходный массив также смещается (остается без первого элемента).

```js
const array = ['1st', '2nd', '3rd']
array.shift() // -> '1st'
array // -> ['2nd', '3rd']
```

* `unshift()` – добавляет элементы в начало массива со смещением. Возвращает новую длину массива.

```js
const array = ['3rd', '4th', '5th', 'last']
array.unshift('1st', '2nd') // -> 6
array // -> ['1st', '2nd', '3rd', '4th', '5th', 'last']
```

#### Работа с концом массива

* `pop()` – извлекает и возвращает последний элемент массива. Исходный массив также изменяется (остается без последнего элемента).

```js
const array = [10, 'JavaScript', 101]
array.pop() // -> 101
array // -> [10, 'JavaScript']
```

* `push()` – добавляет элементы в конец массива. Возвращает новую длину массива.

```js
const array = ['Ecma']
array.push('Script', 2015) // -> 3
array.join() // -> 'Ecma,Script,2015'
```

#### Поиск элементов массива

* `indexOf(searchElement, fromIndex)` – возвращает индекс первого найденного элемента, соответствующего `searchElement`.

```js
const drinks = ['water', 'tea', 'coffee', 'cacao']
const firstAppleIndex = drinks.indexOf('water') // -> 0
const secondAppleIndex = drinks.indexOf('water', 2); // -> 3
```

* `lastIndexOf(searchElement, fromIndex)` – возвращает индекс последнего найденного элемента, соответствующего `searchElement`.

```js
const vegetables = ['tomato', 'cucumber', 'carrot', 'eggplant']
const lastAppleIndex = vegetables.lastIndexOf('tomato') // -> 3
```

* `includes(searchElement, fromIndex)` – определяет, содержит ли массив `searchElement`.

```js
const fruits = ['apple', 'banana', 'orange']
const hasApple = fruits.includes('apple') // -> true
const hasMango = fruits.includes('mango') // -> false
```

* `find(callbackFn, thisArg)` – возвращает первый элемент, удовлетворяющий условию, заданному `callbackFn`.

```js
const numbers = [5, 12, 8, 130, 44]
const foundNumber = numbers.find(element => element > 10) // -> 12
```

* `findIndex(callbackFn, thisArg)` – возвращает индекс первого элемента, удовлетворяющего условию, заданному `callbackFn`.

```js
const numbers = [5, 12, 8, 130, 44]
const foundIndex = numbers.findIndex(element => element > 10) // -> 1
```

#### Итерация по элементам массива

* `forEach(callbackFn, thisArg)` – выполняет `callbackFn` для каждого элемента массива.

```js
const numbers = [1, 2, 3, 4]
numbers.forEach(element => console.log(element * 2)) // -> 2, 4, 6, 8
```

* `map(callbackFn, thisArg)` – создает новый массив с результатами вызова `callbackFn` для каждого элемента.

```js
const numbers = [1, 2, 3, 4]
const doubledNumbers = numbers.map(element => element * 2) // -> [2, 4, 6, 8]
```

#### Сведение массива к одному значению

* `reduce(callbackFn, initialValue)` – применяет `callbackFn` к аккумулятору и каждому элементу массива, чтобы получить одно значение.

```js
const numbers = [1, 2, 3, 4]
const sum = numbers.reduce((accumulator, element) => accumulator + element, 0) // -> 10
```

* `reduceRight()` – то же, что и `reduce()`, но применяет callback-функцию к элементам массива в обратном порядке (справа-налево).

```js
const numbers = [1, 2, 3, 4, 5]
// Вычисление факториала 5 (5! = 5 * 4 * 3 * 2 * 1)
const factorial = numbers.reduceRight((acc, number) => acc * number, 1)
console.log(factorial) // -> 120
```

В примере выше callback-функция умножает аккумулятор `acc` на каждый элемент массива, начиная с последнего элемента `5` и заканчивая первым `1`.

#### Преобразование массива

* `copyWithin()` – копирует часть элементов массива в другую позицию внутри того же массива, перезаписывая существующие элементы.

```js
// Копируем элементы с индекса 1 (включительно)
// начиная с позиции индекса 0
// до индекса 3 (не включительно)
[1, 2, 3, 4, 5].copyWithin(1, 0, 3) //-> [1, 1, 2, 3, 5]
```

* `fill()` – заполняет элементы массива статическим значением.

```js
const numbers = [1, 2, 3, 4, 5]

// Заполнит все элементы массива значением 0
numbers.fill(0) // -> [0, 0, 0, 0, 0]

// Заполнит значением 9
// элементы с индекса 1 (включительно)
// до индекса 4 (не включительно)
numbers.fill(9, 1, 4) // -> [0, 9, 9, 9, 0]
```

* `flat()` – создает новый массив, рекурсивно объединяя элементы вложенных массивов.

```js
const nestedArray = [1, 2, [3, 4], [5, [6, 7]]]

const flatArray = nestedArray.flat(2) // Уровень вложенности 2

console.log(flatArray) // [1, 2, 3, 4, 5, 6, 7]
```

* `flatMap()` – сначала применяет функцию к каждому элементу массива, а затем объединяет результаты в новый массив.

```js
const numbers = [1, 2, 3, 4]

const doubledAndFlattened = numbers.flatMap(number => [number, number * 2])

console.log(doubledAndFlattened) // [1, 2, 2, 4, 3, 6, 4, 8]
```

#### Другие методы массива

* `isArray(obj)` – определяет, является ли объект массивом.

```js
Array.isArray([]) // -> true
Array.isArray({}) // -> false
```

* `toLocaleString()` – возвращает строковое представление массива с учетом локали.

```js
prices = [7890, 120.31]

// Форматирование цен с учетом локали
formattedPrices = prices.toLocaleString('kk', {
style: 'currency', currency: 'KZT'
})

console.log(formattedPrices) // -> 7 890,00 KZT, 120,31 KZT
```

* `toReversed()` – создает новый массив с элементами в обратном порядке по сравнению с исходным массивом.

```js
[1, 2, 3, 4, 5].toReversed() // -> [5, 4, 3, 2, 1]
```

* `toSorted()` – создает новый отсортированный массив на основе исходного массива.

```js
[3, 1, 4, 2, 5].toSorted() // -> [1, 2, 3, 4, 5]
```

* `toSpliced()` – создает новый массив, применяя операцию `splice()` к исходному массиву.

```js
// Начиная с индекса 1
// удаляем 2 элемента
// и вставляем элементы 10 и 20
[1, 2, 3, 4, 5].toSpliced(1, 2, 10, 20) // -> [1, 10, 20, 4, 5]
```

## Встроенные объекты

В JavaScript все на самом деле является объектом или связано с объектом. Даже примитивные типы данных (числа, строки, логические значения, ...) наследуют свойства и методы от своих соответствующих глобальных объектов – Number, String и Boolean, а те в свою очередь являются унаследованными объектами глобального объекта, который так и называется Object.

### Глобальный объект

_Глобальный объект_ (Global Object) в JavaScript представляет собой специальный объект, доступный в любой точке кода и содержащий набор встроенных свойств и методов.

_Глобальный объект_ также содержит ряд других встроенных объектов, таких как Object, Array, Date и Math, которые представляют собой конструкторы объектов и предоставляют различные методы для работы с соответствующими объектами.

Важно отметить, что в браузерной среде глобальный объект `window` представляет собой глобальный объект JavaScript, который содержит все встроенные свойства и методы, а также предоставляет доступ к DOM (Document Object Model) и BOM (Browser Object Model).

#### Глобальные свойства

| Свойство | Определение |
|:-----------:|-------------------------------------------------------------------------------|
| `±Infinity` | больше/меньше чем любое положительное/отрицательное число включая самого себя |
| `NaN` | тоже что и `Number.NaN`. Значение NaN не равно самому себе, т.е. `NaN != NaN` |
| `undefined` | неопределенное значение |

#### Глобальные методы

| Метод | Описание |
|:--------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `alert()` | выводит модальное окно с сообщением |
| `isFinite()` | проверяет, является ли аргумент конечным числом. Возвращает `false`, если аргумент является `NaN`, `Infinity` или `-Infinity` |
| `isNaN()` | является ли аргумент значением `NaN`. Метод пытается преобразовать переданный параметр в число и если это удается, то возвращается `true` |
| `parseInt()` | преобразует аргумент в целое число. Также можно передать вторым параметром основание для преобразования в систему счисления. Если в преобразуемом значении (первом параметре) встретится число или буква не входящая в диапазон системы счисления, то возвращается преобразованное значение полученное на данный момент (по умолчанию преобразует в 10-ую с.с.) |
| `parseFloat()` | преобразует аргумент в число, но допускает одно вхождение точки |
| `prompt()` | выводит окно для ввода пользовательского текста. Используется когда необходим ввод каких-нибудь данных от пользователя |
| `encodeURI()` | кодирует URI, заменяя каждое вхождение определенных символов на escape-последовательности, представляющие символ в кодировке UTF-8 |
| `decodeURI()` | декодирует закодированную методом `encodeURI()` строку |
| `eval()` | переданный параметр рассматривается как код на JavaScript |

#### Примеры использования

```js
isNaN(0) // -> false
isFinite(Math.sqrt(-1)) // -> false

// Преобразование строки в число
const distance = '95.5km'
parseInt(distance) // -> 95
parseFloat(distance) // -> 95.5
parseFloat('$9000') // -> NaN
parseInt('ff', 16) // -> 255
const digits = 255
digits.toString(16) // -> 'ff', не имзеняет исходное значение,
// а возвращает новое в виде строки

// prompt всегда возвращает значение типа String
const myPrompt = prompt('Подсказка', 'значение')

// encodeURI
const uri = encodeURI('http://example.com/phones?item=Apple%20iPhone')
// Декодирование закодированных методом encodeURI() строки
decodeURI(uri)

// eval переданный параметр рассматривает как код на JavaScript
eval('alert("Hello")')
```

### Number

#### Свойства Number

У объекта _Number_ есть статические свойства (константы):

| Свойство | Определение |
|:------------------------:|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Number.MAX_VALUE` | возвращает наибольшее число, которое может быть использовано в JavaScript. Зависит от машины которая в данный момент исполняет скрипт. Примерно равно 1.7976931348623157e+308 |
| `Number.MIN_VALUE` | обратное `Number.MAX_VALUE`. Примерно равно 5E-324 |
| `Number.POSITIVE_INFINITY` | возвращает `Infinity` (+бесконечность). Значение большее любого положительного числа |
| `Number.NEGATIVE_INFINITY` | возвращает `-Infinity` (-бесконечность). Значение, которое меньше любого отрицательного числа |
| `Number.NaN` | особое значение Not a Number, которое сообщает что результатом арифметического выражения является не число |

#### Методы Number

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

| Метод | Описание |
|:----------------------:|----------------------------------------------------------------|
| `Number.toFixed()` | округляет число на длину переданного параметра _после запятой_ |
| `Number.toExponential()` | экспоненциальное представление того же числа |
| `Number.toPrecision()` | округляет число на длину переданного параметра |
| `Number.toString()` | преобразования числа в строку |

Метод `toString()` объекта `Number` перегружен от глобального метода `toString()` и может принимать параметр (число или строку значением от 2 до 36), который будет использован как основание для преобразования в переданную параметром систему счисления.

```js
const digits = 12.3456789
digits.toFixed(3) // -> 12.346
digits.toExponential(5) // -> 1.23457e+1
digits.toPrecision(5) // -> 12.346

const numbers = 255
numbers.toString(16) // -> ff (255 в 16-ричной системе счисления)
```

### String

#### Свойства String

_length_ – длина строки на единицу превосходящее максимальный индекс строки. Свойство `length` у строк доступно только для чтения и недоступно для записи, как например, свойство `length` типа Array.

```js
'Строка длиной 25 символов'.length; // -> 25
```

#### Методы String

Все методы объекта _String_ не изменяют исходную строку, а возвращают новую. Отсчет позиции начинается с нуля. Если аргумент отрицателен (и метод принимает отрицательные значения), то отсчет начинается с конца и с единицы.

| Метод |Описание|
|:------------------:|---|
| `concat()` |возвращает новую конкатенированную строку не изменяя исходную|
| `toLowerCase()` |переводит строку в нижний регистр|
| `toUpperCase()` |переводит строку в верхний регистр|
| `charAt()` |возвращает символ указанной позиции. Отсчет позиции начинается с нуля|
| `charCodeAt()` |возвращает число, соответствующее позиции в таблице кодировки Unicode|
| `fromCharCodeAt()` |возвращает символ, соответсвующий указанной позиции в таблице кодировки Unicode. Статический метод, обращение к нему происходит через сам объект `String.fromCharCodeAt()`|
| `slice()` |возвращает часть строки. Отсчет позиции второго аргумента начинается с начала строки, если аргумент отрицательный, то отсчет начинается с единицы от конца строки|
| `substring()` |возвращает подстроку строки. Если параметр меньше нуля, то он считается как нуль, т.е. метод `substring()` отрицательных значений не принимает. Отсчет позиции второго аргумента начинается с начала строки, если второй аргумент оказывается меньше первого аргумента, то значения параметров меняются местами|
| `substr()` |возвращает подстроку строки (метод не описан в стандарте языка). Отсчет второго аргумента начинается с позиции первого аргумента. Если второй аргумент меньше нуля, то он считается как нуль, т.е. метод не принимает отрицательных значений|
| `indexOf()` |находит и возвращает позицию первого вхождения подстроки. Если найти не удается, то возвращает `-1`. Второй параметр (если передается) указывает с какой позиции начинать поиск|
| `lastIndexOf()` |находит и возвращает позицию первого вхождения подстроки с конца. Второй параметр (если передается) ограничивает поиск от начала до указанной позиции. Возвращает `-1` если искомая подстрока не найдена|
| `replace()` |заменяет совпадение(-ия) регулярного выражения или подстроки в строке. Метод применяется к строке к которой нужно произвести замену. Первый параметр — искомая подстрока или регулярное выражение, второй параметр — строка на которую будут заменены все совпадения|
| `split()` |разбивает строку на массив по указанной подстроке или регулярному выражению. Если в качестве разделителя передать пустую строку, то возвратится массив из элементов строки (символов). Второй параметр — максимальное количество кусков, на которые может быть разбита строка|
| `search()` |возвращает позицию первого вхождения совпадающее с регулярным выражением или с подстрокой. Если совпадений нет, то возвращает `-1`|
| `match()` |возвращает массив, содержащий результаты поиска. Если в регулярном выражении установлен флаг `g`, метод возвращает массив всех соответствий, присутствующих в строке. Например: `"1 плюс 2 равно 3".match(/\d+/g)` вернет `["1", "2", "3"]`. Возвращает `null` если совпадений нет|

#### Примеры String

Конкатенация

```js
const str1 = 'строка '

str1.concat('была', ' конкатенирована')
// -> "строка была конкатенирована"

String.concat('Метод ', 'concat() ', 'объекта ', 'String')
// -> "Метод concat() объекта String"
```

Регистр символов

```js
const str2 = 'эта в нижнем регистре, А ЭТО В ВЕРХНЕМ'

str2.toLowerCase()
// -> "это в нижнем регистре, а это в верхнем"

str2.toUpperCase()
// -> "ЭТО В НИЖНЕМ РЕГИСТРЕ, А ЭТО В ВЕРХНЕМ"
```

Получение символа из строки

```js
const str3 = 'Получение символа из строки'

str3.charAt(12) // -> "м"
// если указанная позиция превышает длину строки,
// то возвратится пустая строка
str3.charAt(120) // -> "" (пустая строка)

str3.charCodeAt(12) // -> 1084
// если указанная позиция превышает длину строки,
// то возвратится NaN
str3.charCodeAt(120) // -> NaN

String.fromCharCode(83, 99, 114, 105, 112, 116) // -> "Script"
```

Получение части строки

```js
const str4 = 'строка для примера'

// без параметров
str4.slice() // -> "строка для примера"
str4.substring() // -> "строка для примера"
str4.substr() // -> "строка для примера"

// с одним положительным параметром
str4.slice(11) // -> "примера"
str4.substring(11) // -> "примера"
str4.substr(11) // -> "примера"

// с одним отрицательным параметром
str4.slice(-7) // -> "примера"
str4.substring(-7) // -> "строка для примера"
str4.substr(-7) // -> "примера"

// первый параметр < второго параметра
str4.slice(7, 10) // -> "для"
str4.substring(7, 10) // -> "для"
// отсчет 2-го параметра substr() начинается с начала строки
str4.substr(7, 10) // -> "для пример"

// первый параметр > второго параметра
str4.slice(10, 7) // -> ""
// substring() поменяет местами аргументы, все равно что 7, 10
str4.substring(10, 7) // -> "для"
str4.substr(10, 7) // -> " пример"

// варианты с положительными и отрицательными параметрами
str4.slice(7, -8) // -> "для"
str4.slice(-11, 10) // -> "для"
str4.slice(-11, -8) // -> "для"
// substring() поменяет местами аргументы
str4.substring(6, -5) // -> "строка", все равно что 0, 6
str4.substring(-10, 6) // -> "строка", все равно что 0, 6
str4.substring(-10, -6) // -> "", все рано что 0, 0
str4.substr(7, -8) // -> "", все равно что 7, 0
str4.substr(-11, 3) // -> "для"
str4.substr(-11, -8) // -> "", все равно что -11, 0
```

Поиск подстроки в строке

```js
const str5 = 'это — просто пример'

str5.indexOf('пр') // -> 6
// поиск подстроки начнется с указанной позиции – 7
str5.indexOf('пр', 7) // -> 13
// если указанный набор символов не найден, то возвратится -1
str5.indexOf('г') // -> -1

str5.lastIndexOf('пр') // -> 13
// второй аргумент ограничивает поиск от начала до указанной позиции
str5.lastIndexOf('пр', 7) // -> 6
```

Замена в строке

```js
const str6 = 'Это строка для замены некой подстроки'

str6.replace('строк', 'линейк')
// -> "Это линейка для замены некой подстроки"

str6.replace(/строк/g, 'линейк')
// -> "Это линейка для замены некой подлинейки"

const str7 = 'Моя кошка любит есть рыбу и молоко'
const str8 = str7.replace(
/кошка|рыбу/g,
match => match === 'кошка' ? 'собака' : 'мясо'
)
str8 // -> "Моя собака любит есть мясо и молоко"
```

Разбиение строки на массив

```js
const str9 = 'Эта строка будет разбита на мелкие кусочки'
str9.split(' ')
// -> ["Эта", "строка", "будет", "разбита", "на", "мелкие", "кусочки"]

// второй аргумент указывает максимальное количество кусков
// на которые может быть разбита строка
str9.split('', 10)
// -> ["Э", "т", "а", " ", "с", "т", "р", "о", "к", "а"]
```

Поиск в строке по регулярному выражению

```js
const mail = '[email protected]'
const re = 'protonmail|gmail|hotmail|yahoo|live'

mail.search(re) // -> 8

// Возврат совпадений с шаблоном регулярного выражения
'ABCDEF'.match(/(ABC)(DE)(F)/) // -> ["ABCDEF, ABC, DE, F"]
```

### Math

В отличие от других глобальных объектов, _Math_ не является конструктором. Все свойства и методы _Math_ статичны.

#### Свойства Math

| Свойство | Определение |
|:-------------:|-----------------------------------------------------------------------------------------|
| `Math.E` | константа Эйлера, основание натурального логарифма, приблизительно 2.718 |
| `Math.LN2` | натуральный логарифм 2, приблизительно 0.693 |
| `Math.LOG2E` | логарифм E по основанию 2, приблизительно 1.442 |
| `Math.LOG10E` | логарифм E по основанию 10, приблизительно 0.434 |
| `Math.PI` | отношение длины окружности к ее диаметру, приблизительно 3.14159 |
| `Math.SQRT12` | квадратный корень из 1/2; иначе говоря, 1 поделить на корень из 2, приблизительно 0.707 |
| `Math.SQRT2` | квадратный корень из 2, приблизительно 1.414 |
| `Math.LN10` | натуральный логарифм 10, приблизительно 2.302 |

#### Методы Math

| Свойство | Определение |
|:---------------:|-----------------------------------------------------------------------------------------------------|
| `Math.abs()` | возвращает абсолютное значение числа |
| `Math.acos()` | возвращает арккосинус (в радианах) от числа |
| `Math.asin()` | возвращает арксинус (в радианах) от числа |
| `Math.atan()` | возвращает арктангенс (в радианах) от числа |
| `Math.atan2()` | возвращает арктангенс частного аргументов |
| `Math.ceil()` | округляет в большую сторону |
| `Math.floor()` | округляет в меньшую сторону |
| `Math.cos()` | вычисляет косинус числа |
| `Math.sin()` | вычисляет синус числа |
| `Math.exp()` | возвращает `Ex`, где `x` - аргумент, а `E` - основание натуральных логарифмов |
| `Math.log()` | возвращает натуральный (по основанию `E`) логарифм числа |
| `Math.pow()` | возводит число в степень, возвращает `base exponent` |
| `Math.max()` | возвращает наибольший из списка аргументов |
| `Math.min()` | возвращает наименьший из списка аргументов |
| `Math.random()` | возвращает псевдослучайное число в интервале `[0, 1]`, т.е. между 0 (включительно) и 1 (не включая) |
| `Math.round()` | возвращает значение, округленное до ближайшего целого числа |
| `Math.sqrt()` | возвращает квадратный корень из числа |
| `Math.tan()` | возвращает тангенс числа |

### Date

Объект _Date_ – содержит методы для работы с датой и временем.

* Время в JavaScript измеряется в миллисекундах, начиная от полуночи 01 января 1970 года GMT+0. День содержит 86,400,000 миллисекунд.

Дата в JavaScript поддерживается в двух форматах:
* _Greenwich Mean Time (GMT)_
* Дата и время указывается в соответствии с местным часовым поясом;
* Указывается смещение относительно Гринвичского меридиана;
* Смещение зависит от переходов на летнее и зимнее время.
* _Universal Time Coordinated (UTC)_
* Дата и время в любой точке планеты одинаково;
* Точка отсчета совпадает с точностью до долей секунды с точкой отсчета GMT;
* Никаких переходов на летнее и зимнее время в UTC нет.

#### Создание даты

```js
const now = new Date() // Местное время в момент иницилизации
const newDate = new Date(dateVal)
```

Если параметр `dateVal` является числовым, то он интерпретируется как количество миллисекунд от `1-Янв-1970 00:00`. Если строкой, то она разбирается и интерпретируется как дата по стандартным правилам `Date.parse`.

Конструктору объекта _Date_ можно передать конкретное время в виде (год, месяц с нуля, день, часы, минуты, секунды, миллисекунды).

```js
const date = new Date(year, month, date[, hours, minutes, seconds, ms])
const date1 = new Date('Jan 01 2024 01:00:00')
const date2 = new Date(1682995487612) // Временая метка
const date3 = new Date(2025, 5) // обязательные параметры: год и номер месяца
const date4 = new Date(2025, 5, 21)
const date5 = new Date(2024, 12, 120) // -> 30 апреля 2025
const date6 = new Date(2025, -1) // -> декабрь, 2014
```

#### Методы Date

| Метод | Описание |
|:------------------------:|---------------------------------------------------------------------------------------------------------------------------------------------|
| `Date.UTC()` | Вычисляет количество миллисекунд, истекших с полуночи 1 января 1970 года до указанной даты, используя время в диапазоне формата UTC |
| `Date.parse()` | Анализирует строку, содержащую дату, и возвращает количество миллисекунд, прошедших с полуночи 1 января 1970 г. UTC до указанной даты |
| `toLocaleString()` | Возвращает дату, преобразованную в строковую величину в соответствии с текущими локальными установками |
| `getDate()` | Возвращает день месяца для указанной даты (согласно местному времени) |
| `getDay(0-6)` | где, 0 — воскресенье. Возвращает день недели для указанной даты (согласно местному времени) |
| `getFullYear()` | Возвращает год для указанной даты (согласно местному времени) |
| `getMilliseconds()` | Возвращает количество миллисекунд для указанной даты (согласно местному времени) |
| `getMinutes()` | Возвращает значение минут для указанной даты (согласно местному времени) |
| `getMonth()` | Возвращает месяц для указанной даты (согласно местному времени) |
| `getSeconds()` | Возвращает значение секунд для указанной даты (согласно местному времени) |
| `getTime()` | Возвращает численное значение для указанной даты (согласно универсальному времени) |
| `getTimezoneOffset()` | Возвращает смещение универсального времени относительно местного в минутах |
| `getUTCDate()` | Возвращает день месяца для указанной даты (согласно универсальному времени) |
| `getUTCDay()` | Возвращает день недели для указанной даты (согласно универсальному времени) |
| `getUTCHours()` | Возвращает час для указанной даты (согласно универсальному времени) |
| `getHours()` | Возвращает час для указанной даты (согласно местному времени) |
| `getUTCMilliseconds()` | Возвращает количество миллисекунд для указанной даты (согласно универсальному времени) |
| `getUTCMonth()` | Возвращает месяц для указанной даты (согласно универсальному времени) |
| `getUTCMinutes()` | Возвращает значение минут для указанной даты (согласно универсальному времени) |
| `getUTCSeconds()` | Возвращает значение секунд для указанной даты (согласно универсальному времени) |
| `getYear()` | Возвращает сокращённое значение года для указанной даты (согласно местному времени) |
| `setSeconds(0-59)` | Устанавливает для указанной даты значение секунд равным указанному (согласно местному времени) |
| `setFullYear()` | Устанавливает для указанной даты год равным указанному значению (согласно местному времени) |
| `setMilliseconds(0-999)` | Устанавливает для указанной даты значение миллисекунд равным указанному (согласно местному времени) |
| `setTime()` | Устанавливает численное значение для указанной даты в миллисекундах, прошедших после полночи 1 января 1970 года (по универсальному времени) |
| `setYear()` | Устанавливает для указанной даты год равным указанному значению (согласно местному времени) |
| `setDate(1-31)` | Устанавливает день месяца равным указанному значению (согласно местному времени) |
| `setUTCDate()` | Устанавливает день месяца равным указанному значению (согласно местному времени) |
| `setUTCHours()` | Устанавливает для указанной даты час равным указанному значению (согласно универсальному времени) |
| `setHours()` | Устанавливает для указанной даты час равным указанному значению (согласно местному времени) |
| `setUTCMilliseconds()` | Устанавливает для указанной даты значение миллисекунд равным указанному (согласно местному времени) |
| `setUTCMinutes()` | Устанавливает для указанной даты значение минут равным указанному (согласно универсальному времени) |
| `setMinutes(0-59)` | Устанавливает для указанной даты значение минут равным указанному (согласно местному времени) |
| `setMonth(0-11)` | Устанавливает для указанной даты месяц равным указанному значению (согласно местному времени) |
| `setUTCSeconds()` | Устанавливает для указанной даты значение секунд равным указанному (согласно местному времени) |
| `setUTCFullYear()` | Устанавливает для указанной даты год равным указанному значению (согласно универсальному времени) |
| `setUTCMonth()` | Устанавливает для указанной даты месяц равным указанному значению (согласно местному времени) |
| `toGMTString()` | Преобразовывает дату в строку (согласно времени по Гринвичу) |
| `toLocaleFormat()` | Преобразовывает дату в строку согласно текущим языковым настройкам и указанному формату |
| `toLocaleTimeString()` | Возвращает информацию о дате в виде текстовой строки согласно языковым настройкам системы |
| `toLocaleDateString()` | Возвращает информацию о дате в виде текстовой строки согласно языковым настройкам системы |
| `toString()` | Возвращает строку, представляющую текущий объект Date. |
| `toTimeString()` | Возвращает информацию о дате в виде текстовой строки в американском формате записи даты |
| `toDateString()` | Возвращает информацию о дате в виде текстовой строки в американском формате записи даты |
| `toUTCString()` | Преобразовывает дату в строку (согласно универсальному времени) |
| `valueOf()` | Возвращает примитивное значение объекта Date |
| `getUTCFullYear()` | Возвращает год для указанной даты (согласно универсальному времени) |

### Регулярные выражения

#### Создание RegExp

```js
// Полная форма
const pattern1 = new RegExp(pattern [, flags])

// Сокращенная форма (литеральный формат)
const pattern2 = /pattern/flags

// Динамическое создание регулярного выражения
const emails = ['gmail', 'yahoo', 'hotmail', 'live', 'outlook']
const re = new RegExp(emails.join('|', 'i'))
// -> /gmail|yahoo|hotmail|live|rambler/i
```

где,
- `pattern` – шаблон регулярного выражения;
- `flags` – способ поиска по шаблону, порядок указания флагов не имеет значения, может принимать следующие значения:

| Флаг | Значение |
|:----:|--------------------------------------------------------------------|
| `g` | глобальный поиск (обрабатываются все совпадения с шаблоном поиска) |
| `i` | поиск без учета регистра |
| `m` | многострочный поиск |

#### Специальные последовательности

| Последовательность | Описание |
|:------------------:|------------------------------------------------------------------------------------------------|
| `\'` | одинарные кавычки (апостроф) |
| `\"` | двойные кавычки |
| `\\` | обратный слеш (`\u005C`) |
| `\b` | backspace |
| `\f` | form feed |
| `\n` | переход на новую строку (`\u000A`) |
| `\r` | возврат каретки (`\u000D`) |
| `\t` | табуляция (`\u0009`) |
| `\v` | вертикальная табуляция |
| `\0` | символ NULL (`\u0000`) |
| `\ddd` | octal sequence (3 digits: ddd) |
| `\xdd` | hexadecimal sequence (2 digits: dd). Символ Latin-1, заданный двумя шестнадцатеричными цифрами |
| `\u{X...X}` | символ Unicode с кодом от `X...X` (от 1 до 6 шестнадцатеричных цифр) |

#### Позиции соответствия

| Знак | Значение |
|:----:|--------------------------------------------------------------------------------------------------------------------|
| `^` | соответствует началу строки, т.е. выражение `/^a/` найдет соответствие если строка начинается строго с символа `а` |
| `$` | соответствует концу строки, т.е. выражение `/b$/` найдет соответствия только если строка заканчивается на `b` |
| `\b` | позиция между символом ASCII `[a-zA-Z0-9_]` и не символом ASCII `[^a-zA-Z0-9_]` (граница слова) |
| `\B` | позиция между двумя символами ASCII (не граница слова) |

#### Операторы регулярного выражения

| Оператор | Значение |
|:--------:|---------------------------------------------------------------------------------------------------------------|
| `\` | обратный слеш, экранирует спецсимволы `*`, `+`, `?`, `❘`, `(`, `)`, `[`, `{`, `}`, `.`, `$` и `\`. |
| `.` | любой символ, кроме перевода строки (`\n`) |
| `[]` | перечень символов перечисленных в наборе |
| `-` | указывается в диапазоне символов |
| `[a-e]` | диапазон символов, тоже что и `[abcde]` |
| `[^a-e]` | перечень символов, не входящие в набор, тоже что и `[^abcde]` |
| `()` | выделение групп регулярных выражений с присвоением порядкового номера для извлечения подстроки |
| `(?:x)` | захватывает соответствующее выражение без присваивания порядкового номера |
| `x(?=y)` | соответствует `x`, только если за ним следует `y` |
| `x(?!y)` | соответствует `x`, только если за ним НЕ следует `y` |
| `❘` | оператор ИЛИ |
| `{}` | находит повторения (примеры ниже) |
| `{n}` | шаблон повторяется точно `n` раз. Например, `/a{3}/` найдет ровно три символа `а` идущих один за другим |
| `{n,}` | шаблон повторяется не менее `n` раз. Например, `/a{3,}/` найдет 3 или более идущих один за другим символов `а` |
| `{n,m}` | шаблон повторяется не менее `n`, но и не более `m` раз. Например, `/a{5,10}/` ищет от 5 до 10 символов `а` |
| `\b` | соответствует границе слова |
| `\B` | соответствует любому месту, где нет границы слова |
| `\d` | любая цифра `[0-9]` |
| `\D` | противоположное `\d` `[^0-9]` |
| `\s` | любой символ-разделитель Unicode (`\r`, `\n`, `\t`, `\v`, пробел, ...) |
| `\S` | противоположное `\s` |
| `\w` | любой символ ASCII `[a-zA-Z0-9_]` |
| `\W` | противоположное `\w` (`[^a-zA-Z0-9_]`) |

#### Квантификаторы

| Вид | Значение |
|:---:|------------------------------------------------------------------|
| `*` | эквивалентно `{0,}` (может не быть, а может сколько угодно быть) |
| `+` | эквивалентно `{1,}` (минимум одно вхождение, но должно быть) |
| `?` | эквивалентно `{0,1}` (может быть, а может не быть) |

#### Методы регулярного выражения

| Метод | Значение |
|:--------:|---------------------------------------------------------------------------------------------------------------------------------------------------|
| `test()` | обратно методу `search()` проверяет совпадение регулярного выражения в передаваемой строке. Возвращает `true` если есть совпадения, иначе `false` |
| `exec()` | возвращает массив с результатами поиска по шаблону, если совпадений нет, то возвращается `null` |

#### Примеры RegEx

Экранирование и перечисления

```js
'folder/file.js'.search(/\//) // -> 6, экранирование прямого слеша
/[abcde]/.test('protocol') // -> true, найден символ "c" указанный в наборе
'ecmascript'.search(/[^a-e]/) // -> 2, найден символ "m", первый символ не входящий в набор
```

Повторения `{n}`, `{n,m}`, `{n,}`

```js
const str = `JavaScript – объектно-ориентированный язык.
Но используемое в языке прототипирование обуславливает
отличия в работе с объектами по сравнению с традиционными
класс-ориентированнннными языками`

str.search(/н{1}/) // -> 19, позиция символа "н", который встречается в 1-ый раз
str.search(/н{2,5}/) // -> 33, позиция символа "н", который впервые встречатся после 2 до 5 раз
str.search(/н{5,}/) // -> 174, позиция символа "н", который встречается после 5 раз и более раза
/js{3}/.test('jsjsjs') // -> false, на самом деле будет искаться вхождение подстроки "jsss"
```

Позиции соответствия

Спецсимвол `^` в начале и спецсимвол `$` в конце, говорят что строка должна строго начинаться и заканчиваться в соответствии с шаблоном регулярного выражения.

```js
/^\d\d?-\d\d?-\d{4}$/
/\bJava\b/.test('Java Script') // -> true
/\BScript\b/.test('JavaScript') // -> true
```

Флаги

```js
const str = 'JavaScript\nis\nthe\nprogramming\nlanguage\nof\nthe\nWeb'
str.search(/s/i) // -> 4, ищется как "s", так и "S"
str.search(/^language/m) // -> 30, многострочный поиск
```

Группировка и ссылки

```js
// Внутренние ссылки (ссылка в шаблоне регулярного выражения)
const str1 = 'JavaScript is using the "Unicode\' character set'
const str2 = 'JavaScript is using the "Unicode\" character set'
str1.search(/["'][^"']*["']/) // -> 24
str1.search(/(["'])[^"']*\1/) // -> -1
str2.search(/(["'])[^"']*\1/) // -> 24

// Внешние ссылки (ссылка вне шаблона регулярного выражения)
'Script Java'.replace(/(\w+) (\w+$)/, '$2$1') // -> "JavaScript"
const beatles = `
Lennon, John
McCartney, Paul
Harrison, George
Starr, Ringo`
beatles.replace(/([\w ]+), ([\w ]+)/g, '$2 $1')
// -> "John Lennon\nPaul McCartney\nGeorge Harrison\nRingo Starr"

// Возврат совпадений с шаблоном регулярного выражения
/(ABC)(DE)(F)/.exec('ABCDEF') // -> ["ABCDEF, ABC, DE, F"]
```

### Error

Объект _Error_ служит для генерации ошибок возникающих в ходе выполнения JavaScript кода. Имеет следующие подклассы _Error_:
* _EvalError_ – ошибка при выполнении `eval()`;
* _RangeError_ – эта ошибка происходит, когда переданный параметр лежит за границами допустимого диапазона;
* _ReferenceError_ – ошибка при разыменовании неверной ссылки;
* _SyntaxError_ – синтаксическая ошибка, которая произошла при разборе кода, переданного `eval()`;
* _TypeError_ – переменная или параметр неправильного типа;
* _URIError_ – ошибка происходит, когда `encodeURI()` или `decodeURI()` вызваны с неправильными параметрами.

Чтобы отловить ошибку применяется конструкция [try..catch..finally](#trycatchfinally).

```js
try {
const x = 10
console.log(y)
} catch(e) {
console.error(e.name) // -> ReferenceError
console.error(e.message) // -> y is not defined
} finally {
console.info('Содержимое конструкции finally выполнится всегда')
}

console.info('Эта инструкция также выполнится')
```

#### Инициирование исключения

Используйте `throw` для генерации исключения, аналогично Java/PHP и другим языкам. В отличие от них, JavaScript позволяет бросать исключение любого формата:

```js
try {
const x = 10
const y = 0

if (y == 0) {
throw RangeError('деление на ноль')
}

const z = x / y
} catch(e) {
console.error(e.name) // -> RangeError
console.error(e.message) // -> деление на ноль
}
```

Еще один вариант использование конструкции `throw`.

```js
try {
throw {
name: 403,
message: 'Access denied'
}
} catch(e) {
console.error(e.name) // -> 403
console.error(e.message) // -> Access denied
}
```

## Объектно-ориентированное программирование

JavaScript, хоть и не является "классическим" объектно-ориентированным языком программирования (ООП), поддержка принципов ООП в нём обеспечена на основе прототипного наследования.

### Принципы ООП

1. **Инкапсуляция** – объединение данных и методов в единую структуру, скрывая внутреннюю реализацию и предоставляя интерфейс для взаимодействия;
2. **Наследование** – создание новых классов (дочерних) на основе существующих (родительских), наследуя их свойства и методы;
3. **Полиморфизм** – способность объектов разных классов с одинаковым интерфейсом иметь различную реализацию, т.е. реагировать на один и тот же вызов метода по-разному. Это может быть достигнуто через перегрузку методов, переопределение методов и использование абстрактных классов и интерфейсов;
4. **Классы** – шаблоны для создания объектов с определенными свойствами и методами;
5. **Объекты и сообщения** – основные строительные блоки, представляющие сущности с данными (свойства) и поведением (методы). ООП сосредотачивается на обмене сообщениями между объектами, что способствует модульности и повышает уровень абстракции в программировании.

В общем и целом, ООП это подход разработки, где программа рассматривается как набор объектов, взаимодействующих друг с другом.

### Функция-конструктор

_Функции-конструкторы_ могут быть использованы для создания объектов с определёнными методами и свойствами. Имена таких функций принято писать с большой буквы.

* Ключевое слово `this` в пределах функции-конструктора ссылается на создаваемый объект;
* Оператор `new` создаёт новый объект путём инициализации функции-конструктора;
* Все типы данных в JavaScript, кроме тривиальных типов (`null`, `undefined`) имеют собственные классы-конструкторы.

```js
function User(name) {
this.name = name
this.age = null
this.greetings = function(word) {
if (typeof word == 'string') {
console.info(`Hello, ${word} from ${this.name}`)
}
return false
}
}

// Иницилизация объектов от конструктора "User"
const user1 = new User('John')
const user2 = new User('Jane')

user1.age = 30
user1.greetings('Alice') // -> "Hello, Alice from John"
user2.greetings('Bob') // -> "Hello, Bob from Jane"
```

Свойство _constructor_ позволяет узнать какой конструктор был использован при создании какой-либо переменной.

* `ИмяОбъекта.constructor` – возвращает конструктор объекта, т.е. функцию-конструктор от которой был создан объект;
* Оператор `instanceof` проверяет принадлежность объекта к цепочке прототипов другого объекта. Другими словами, он проверяет, является ли объект экземпляром определенного класса или его потомков. Оператор не работает с примитивами.

```js
let x = 5
x.constructor; // -> function Number(){[native code]}
user1.constructor // -> код функции-конструктора User

// Оператор instanceof
x instanceof Number // -> false, x здесь примитив
x = new Number(5)
x instanceof Number // -> true, x здесь объект конструктора Number
x instanceof Object // -> true, все объекты наследуются от Object
```

### Прототипы

В JavaScript другой механизм наследования в отличие от других класс-ориентированных языков программирования. В основе ООП в JavaScript лежит _прототипное наследование_, когда каждый объект имеет свойство `prototype`, которое в свою очередь ссылается на другой объект (прототип). Новый объект наследует свойства и методы своего прототипа.

_Прототипное программирование_ – стиль объектно-ориентированного программирования, при котором отсутствует понятие класса, а наследование производится путём клонирования существующего экземпляра объекта (прототипа).

У любой функции определено свойство `prototype` и вступает оно в действие при использовании этой функции с оператором `new`, то есть при использовании ее в качестве функции-конструктора. Это свойство ссылается на так называемый «объект-прототип» – виртуальный предок всех экземпляров этого класса-конструктора. С помощью данного свойства можно создать любое другое свойство или метод, который будет наследоваться всеми экземплярами этого класса-конструктора.

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

Добавление свойства к [вышеописанному](#функция-конструктор) прототипу `User`:

```js
User.prototype.married = false
```

Теперь наследуемые от класса-конструктора `User` объекты `user1` и `user2` имеют свойство `married` со значением `false`.

Альтернативный способ добавления свойств/методов в класс-конструктор через наследуемый от этого конструктора объект.

```js
user1.constructor.prototype.info = function() {
return `Name: ${this.name};
Age: ${this.age};
${this.married ? 'Married: Yes' : 'Married: No'}`
}
```

### Классы

_Классы_ называют синтаксическим сахаром поверх прототипного наследования в JavaScript, делающий код более читаемым и похожим на другие ООП языки.

```js
class Animal {
constructor(species) {
this.species = species
}

breathe() {
console.log('The animal is breathes')
}
}

class Dog extends Animal {
bark() {
console.log('Woof! Woof!')
}
}

const Rex = new Dog('canids')
Rex.breathe() // -> The animal is breathes
Rex.bark() // -> Woof! Woof!
```

## BOM (Объектная модель браузера)

_BOM (Browser Object Model)_ – объектная модель браузера, набор объектов предоставляющий JavaScript доступ к свойствам и методам браузера.

Объект `window` – глобальный объект, корневой узел в браузерной среде свойства и методы которого, являются узлами первого уровня. Фактически, глобальная переменная это свойство данного объекта.

_DOM (Document Object Model)_ – объектная модель документа, представляет содержимое веб-страницы в виде иерархической структуры узлов, с которыми можно взаимодействовать.

_DOM_ является частью _BOM_, поскольку `document` является дочерним объектом корневого объекта BOM — `window`.

Стандартные объекты JavaScript (Function, Object, Date, Math, String, Number, RegExp и т.д.) в браузерной среде также являются частью BOM и могут быть рассмотрены как дочерние узлы объекта `window`. Однако, по сравнению с _DOM_, эти объекты находятся на более низком уровне и не являются частью структуры веб-страницы.

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

```text
window

├── JavaScript
│ ├── Object
│ ├── Number
│ ├── String
│ ├── ...
├── BOM
│ ├── navigator
│ │ ├── geolocation
│ ├── location
│ ├── history
│ ├── screen
├── DOM
│ ├── document
│ │ ├── html
│ │ ├── head
│ │ │ ├── title
│ │ │ ├── meta
│ │ │ ├── ...
│ │ ├── body
│ │ │ ├── header
│ │ │ ├── main
│ │ │ ├── ...
├── XMLHttpRequest
├── setTimeout
├── setInterval
└── ...
```

### Свойства и методы Window

Работа с окнами и фреймами

| Свойство/Метод | Значение |
|:----------------:|--------------------------------------------------------|
| `window.frames` | коллекция фреймов на текущей странице |
| `window.parent` | ссылка на родительское окно текущего фрейма |
| `window.opener` | ссылка на окно, которое открыло текущее окно или фрейм |
| `window.open()` | открывает новое окно браузера или фрейм |
| `window.close()` | закрывает текущее окно браузера |

Работа с окном браузера

| Свойства | Значение |
|:--------------------------:|-------------------------------------------------------------------------------|
| `innerWidth`/`innerHeight` | содержат текущую ширину и высоту окна браузера без учета панелей инструментов |
| `outerWidth`/`outerHeight` | содержат текущую ширину и высоту окна браузера вместе с панелями инструментов |

Положение и размеры окна

| Метод | Описание |
|:----------------:|-----------------------------------------------------------------------------------------------------|
| `moveTo(x, y)` | перемещает окно в абсолютную позицию на экране |
| `resizeTo(x, y)` | устанавливает абсолютные размеры окна |
| `scrollTo(x, y)` | выполняет смещение в указанную позицию координат |
| `moveBy(x, y)` | перемещает окно на x пикселей по горизонтали и y пикселей по вертикали относительно текущей позиции |
| `resizeBy(x, y)` | расширяет или сжимает окно на указанное аргументами количества пикселей |
| `scrollBy(x, y)` | выполняет смещение на указанное количество пикселей |

Работа с диалоговыми окнами

| Метод | Значение |
|:-----------:|----------------------------------------------------------------------------------------|
| `alert()` | выводит модальное диалоговое окно с заданным текстом |
| `prompt()` | выводит модальное диалоговое окно с текстовым полем для ввода пользовательского текста |
| `confirm()` | выводит модальное диалоговое окно с двумя кнопками "ОК" и "Отмена" |

Работа с таймерами

| Метод | Значение |
|:-----------------:|---------------------------------------------------------------------------------|
| `setTimeout()` | вызывает функцию один раз через определенный промежуток времени |
| `setInterval()` | вызывает функцию каждый раз через определенный промежуток времени |
| `clearTimeout()` | отменяет запланированный вызов функции, установленный с помощью `setTimeout()` |
| `clearInterval()` | отменяет запланированный вызов функции, установленный с помощью `setInterval()` |

Вспомогательные методы

| Метод | Значение |
|:--------------:|---------------------------------------------------|
| `isNaN` | проверяет, является ли значение `NaN` (не числом) |
| `isFinite()` | проверяет, является ли значение конечным числом |
| `parseInt()` | преобразует строку в целое число |
| `parseFloat()` | преобразует строку в число с плавающей точкой |

Работа с событиями

| Метод | Описание |
|:-----------------------:|-----------------------------------------------------------------|
| `addEventListener()` | регистрирует функцию обработчика событий на объекте Window |
| `removeEventListener()` | удаляет зарегистрированный обработчик событий из объекта Window |
| `dispatchEvent()` | инициирует событие определенного типа на объекте Window |

Это далеко не полный список всех свойств и методов объекта Window, полный список доступен в [документации](https://developer.mozilla.org/en-US/docs/Web/API/Window).

### Фреймы

Свойство `window.frames` содержит коллекцию всех дочерних фреймов, загруженных в текущую страницу сайта, в том числе и вложенные фреймы в других фреймах.

Внутри каждого фрейма находится собственный `window` с дочерними объектами также, как и в родительском окне. Доступ к фреймам из родительского окна будет иметь в случае только если эти фреймы имеют тот же домен и порт, что и родительское окно.

По соображениям безопасности действует политика _Same Origin Policy (Одинаковый источник)_, которая запрещает скриптам из одной страницы взаимодействовать со страницами, расположенными на других доменах или портах.

#### Работа с окнами

_Создание фреймов на странице_

```html

```

_Обращение к элементам фреймов_

* `frameElement` – ссылка на HTML-элемент, содержащий текущий фрейм;
* `frames[]` – обращение к фрейму по индексу;
* `frames[]` – обращение к фрейму в коллекции по имени;
* `frames.namedItem()` – обращение к фрейму по имени;
* `frames.length` – количество фреймов в коллекции;
* `frames.parent` – родительское окно `window`;
* `frames.self` – ссылка на текущий `window`;
* `frames.top` – родительский `window` верхнего уровня.

Использование фреймов на веб-сайтах не рекомендуется, из-за сложностей в доступности, SEO и безопасность сайта.

### navigator

Объект `window.navigator` содержит информацию о браузере и операционной системе устройства пользователя. В зависимости от этих двух вещей некоторые из свойств этого объекта могут быть недоступны. Следующие свойства одни из наиболее часто используемых:

| Свойство | Описание |
|:---------------------:|------------------------------------------------------------------------------------------------------------|
| `connection` | предоставляет информацию о типе подключения пользователя к интернету (например, Wi-Fi, мобильный интернет) |
| `cookieEnabled` | возвращает булево значение, указывающее, включены ли cookie в браузере |
| `geolocation` | предоставляет доступ к геопозиции пользователя |
| `hardwareConcurrency` | возвращает количество логических процессоров, доступных на устройстве пользователя |
| `mediaDevices` | предоставляет доступ к устройствам ввода, таким как камера и микрофон |
| `onLine` | возвращает булево значение, указывающее, находится ли устройство пользователя в режиме онлайн или офлайн |
| `platform` | возвращает строку, содержащую информацию об операционной системе устройства пользователя |
| `plugins` | возвращает коллекцию объектов `Plugin` с информацией о плагинах, установленных в браузере пользователя |
| `userAgent` | возвращает строку, содержащую информацию о браузере, версии браузера и операционной системе |

Более подробную информацию обо всех свойствах можно найти в [документации](https://developer.mozilla.org/en-US/docs/Web/API/Navigator).

### history

Объект `window.history` предоставляет историю посещений пользователя в текущей вкладке браузера. В целях безопасности объект `window.history` не позволяет получить доступ к хранящимся в объекте URL-адресам, а лишь перемещаться вперед и назад по истории посещений и добавлять в нее новые записи.

| Свойства | Значение |
|:--------:|---------------------------------------|
| `length` | количество записей в истории браузера |

| Методы | Описание |
|:-----------:|----------------------------------------------------------------|
| `back()` | переход на предыдущую страницу в истории браузера |
| `forward()` | переход на следующую страницу в истории браузера |
| `go(n)` | переход на страницу `n` от текущей страницы в истории браузера |

Если `n` в методе `go()` отрицательное, то произойдёт переход на предыдущие страницы, если положительное, то на следующие.

### location

Свойство `window.location` ссылается на объект _Location_, представляющий текущий URL-адрес документа, и определяющий методы для изменения этого адреса. Свойство `document.location` также ссылается на объект _Location_ (`window.location === document.location`).

| Свойство | Значение |
|:----------:|--------------------------------------------------------------------------|
| `href` | полный URL-адрес текущей страницы |
| `protocol` | протокол текущей страницы (например, `http:`, `https:`, `file:`, `ftp:`) |
| `host` | хост и порт текущей страницы (например, `www.example.com:80`) |
| `hostname` | имя хоста текущей страницы (например, `www.example.com`) |
| `port` | порт текущей страницы (например, `80`) |
| `pathname` | путь к текущей странице на сервере (например, `/path/to/page.html`) |
| `search` | строка запроса текущей страницы (например, `?id=123&name=John`) |
| `hash` | якорь текущей страницы (например, `#section1`) |

| Метод | Описание |
|:--------------:|----------------------------------------------------------------|
| `assign(url)` | переход по указанному `url` |
| `replace(url)` | переходит и заменяет текущий `url` на новый в журнале браузера |
| `reload()` | перезагрузка страницы |

По умолчанию метод `reload()` перезагружает документ из кэша, но если передать в качестве параметра `reload(true)`, то страница будет запрошена с сервера, как если было нажато `Ctrl + F5`.

### screen

Свойство `window.screen` ссылается на объект _Screen_, предоставляющий информацию о характеристиках экрана пользователя на котором в данный момент открыта страница.

| Свойство | Значение |
|:-------------:|----------------------------------------------------------------------------------|
| `height` | разрешение экрана по вертикали в пикселях |
| `width` | разрешение экрана по горизонтали в пикселях |
| `colorDepth` | количество битов, используемых для хранения цветовой информации |
| `pixelDepth` | количество битов, используемых для представления цвета каждого пикселя на экране |
| `availHeight` | высота экрана пользователя в пикселях без учета элементов оформления окна |
| `availWidth` | ширина экрана пользователя в пикселях без учета элементов оформления окна |

## Клиентский JavaScript

### Управление загрузкой скриптов. Атрибуты aync и defer

В примере ниже:

* `analytics.js` загрузится и выполнится асинхронно, как только будет доступен.
* `library.js` и `script.js` загрузятся асинхронно, но выполнятся только после завершения парсинга HTML, в указанном порядке.

```html

// Встроенный скрипт, не использует async или defer
// console.log("Этот скрипт выполняется сразу же");

```

**Важно:**

* Не используйте `async` и `defer` для встроенных скриптов (скриптов, написанных непосредственно в HTML).
* Оба атрибута игнорируются для скриптов с атрибутом `src`, содержащим пустую строку.
* Выбор между `async` и `defer` зависит от конкретных потребностей вашего скрипта и его взаимодействия с DOM.

## DOM: Объектная модель документа

_DOM (Document Object Model)_ – объектная модель документа, стандартная спецификация JavaScript, определяющая структуру и способ доступа к элементам и содержимому веб-страницы.

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

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

Объект `document` является главным объектом в объектной модели документа (DOM) и представляет веб-страницу, загруженную в браузере. Он предоставляет доступ к содержимому документа, его структуре и свойствам, и может быть использован для манипуляции с элементами страницы.

### Свойства document

Элементы документа

| Свойство | Значение |
|:--------------------------:|--------------------------------------------------|
| `document.URL` | возвращает текущий URL документа |
| `document.title` | устанавливает или возвращает заголовок документа |
| `document.body` | возвращает объект тела документа |
| `document.head` | возвращает объект заголовка документа |
| `document.documentElement` | возвращает объект корневого элемента документа |

Информация о документе

| Свойство | Значение |
|:-----------------------:|------------------------------------------------------------|
| `document.defaultView` | ссылка на глобальное окно, в котором отображается документ |
| `document.lastModified` | дата последней модификации документа |
| `document.readyState` | статус загрузки документа |
| `document.cookie` | устанавливает или возвращает cookie для текущего документа |

### Методы document

Работы с элементами страницы

| Метод | Описание |
|:--------------------------:|---------------------------------------------------------------------|
| `getElementById()` | возвращает элемент на странице с указанным идентификатором |
| `getElementsByTagName()` | возвращает массив элементов на странице с указанным тегом |
| `getElementsByClassName()` | возвращает массив элементов на странице с указанным классом |
| `querySelector()` | возвращает первый элемент, соответствующий указанному селектору CSS |
| `querySelectorAll()` | возвращает все элементы, соответствующие указанному селектору CSS |

Работа с содержимым страницы

| Метод | Описание |
|:------------------:|--------------------------------------------------------------------------------------|
| `write()` | выводит текст или HTML на страницу в место вызова |
| `createElement()` | создает новый элемент на странице |
| `createTextNode()` | создает новый текстовый узел |
| `appendChild()` | добавляет новый элемент в конец дочерних элементов указанного родительского элемента |
| `replaceChild()` | заменяет указанный дочерний элемент новым элементом |
| `remove()` | удаляет элемент со страницы |

Работа с событиями

| Метод | Описание |
|:-----------------------:|------------------------------------------------------------------------------|
| `addEventListener()` | регистрирует функцию обработчика событий для указанного элемента на странице |
| `removeEventListener()` | удаляет ранее зарегистрированный обработчик событий |
| `createEvent()` | создает новый объект события |
| `dispatchEvent()` | вызывает указанное событие на элементе на странице |

### Типы узлов документа

В _DOM (Document Object Model)_ существуют различные виды узлов, которые представляют разные типы элементов в документе. Некоторые из них перечислены в таблице ниже:

| Код типа | Тип узла | Описание | Пример |
|:--------:|:--------------------------:|------------------------------------------------------------------------------------|------------------------------------|
| 1 | **ELEMENT_NODE** | Узел, который представляет элемент на странице, такой как `div`, `p`, `img` и т.д. | `

...

` |
| 2 | **ATTRIBUTE_NODE** | Узел, который представляет атрибут элемента, такой как `class`, `id`, `src` и т.д. | `align="center"` |
| 3 | **TEXT_NODE** | Узел, который представляет текстовое содержимое элемента | `просто текст` |
| 8 | **COMMENT_NODE** | Узел, который представляет комментарий в HTML-коде | `` |
| 9 | **DOCUMENT_NODE** | Корневой узел, который представляет весь документ | `document.nodeType === 9` |
| 10 | **DOCUMENT_TYPE_NODE** | Узел, который представляет объявление типа документа (doctype) в начале HTML-кода | `` |
| 11 | **DOCUMENT_FRAGMENT_NODE** | Узел, который представляет фрагмент документа, который не имеет корневого узла | `document.createDocumentFragment() |

_Код типа узла_ – это числовое значение, которое указывает на тип конкретного узла в документе. Это свойство `nodeType` доступно для всех узлов в DOM и используется для определения типа узла. Для каждого типа узла существуют свои методы и свойства, которые могут быть использованы в JavaScript. Эти свойства и методы рассмотрены ниже.

### Связи между DOM-элементами

Разберём связи следующих DOM-элементов:

```html

Это простой пример


```

Схематично их можно представить так:

```text


┌────── parentNode ─────>├───── childNodes ─────>
│ │ │
Это <─ previousSibling ─ ─ nextSibling ─> пример

firstChild

простой
```

В данном случае:

* `parentNode` для элементов `Это`, `` и `пример` является элемент `

`;
* `childNodes` для элемента `


` включает элементы `Это`, `` и `пример`;
* `previousSibling` для элемента `` является текстовый узел, содержащий слово `Это`;
* `nextSibling` для элемента `` является текстовый узел, содержащий слово `пример`;
* `firstChild` для элемента `` является текстовый узел, содержащий слово `простой`.

### Свойства и методы типов узлов DOM

_DOM (Document Object Model)_ – это иерархическая структура, которая представляет HTML-документ в виде дерева объектов. Каждый узел в дереве представляет отдельный элемент документа, который может иметь разные типы.

Ниже представлены свойства и методы основных типов узлов DOM.

#### Node

`Node` – является базовым типом узлов и представляет общие свойства и методы, которые присутствуют у всех типов узлов.

| Свойство | Значение |
|:-------------:|--------------------------------------------------------------------------------|
| `childNodes` | возвращает коллекцию всех дочерних узлов данного узла |
| `firstChild` | возвращает первый дочерний узел у данного узла |
| `lastChild` | возвращает последний дочерний узел у данного узла |
| `nextSibling` | возвращает следующий соседний узел от данного узла |
| `nodeName` | возвращает имя узла в виде строки |
| `nodeType` | возвращает тип узла в виде числа |
| `nodeValue` | возвращает или устанавливает значение узла |
| `parentNode` | возвращает родительский узел данного узла |
| `textContent` | возвращает текстовое содержимое всех дочерних узлов данного узла в виде строки |

| Метод | Описание |
|:-----------------------------------:|--------------------------------------------------------------------------------------------|
| `appendChild(node)` | добавляет узел `node` в конец списка дочерних узлов данного узла |
| `cloneNode(deep)` | создает копию данного узла. Если deep равен `true`, то будут скопированы все дочерние узлы |
| `hasChildNodes()` | возвращает `true`, если данный узел имеет дочерние узлы |
| `insertBefore(node, referenceNode)` | вставляет узел `node` перед узлом |
| `removeChild(node)` | удаляет узел `node` из списка дочерних узлов данного узла |
| `replaceChild(newNode, oldNode)` | заменяет узел `oldNode` на узел `newNode` в списке дочерних узлов данного узла |

Полный список свойств и методов Node в [документации](https://developer.mozilla.org/en-US/docs/Web/API/Node).

#### Element

`Element` является подтипом типа `Node` и расширяет его свойства и методы. Этот тип представляет HTML-элементы и имеет ряд специфичных свойств и методов. Ниже приведены наиболее распространенные свойства и методы класса `Element`:

| Свойство | Значение |
|:-----------:|--------------------------------------------------------------------------------------------|
| `classList` | возвращает коллекцию классов данного элемента |
| `className` | возвращает или устанавливает атрибут `class` элемента |
| `id` | возвращает или устанавливает атрибут `id` элемента |
| `innerHTML` | возвращает или устанавливает содержимое элемента в виде HTML-кода |
| `outerHTML` | возвращает или устанавливает содержимое элемента в виде HTML-кода вместе с самим элементом |
| `tagName` | возвращает имя тега элемента в верхнем регистре |

| Метод | Описание |
|:------------------------------:|------------------------------------------------------------------------------------|
| `getAttribute(name)` | возвращает значение атрибута элемента с именем `name` |
| `setAttribute(name, value)` | устанавливает значение атрибута элемента с именем `name` на `value` |
| `hasAttribute(name)` | возвращает `true`, если элемент имеет атрибут с именем `name` |
| `removeAttribute(name)` | удаляет атрибут элемента с именем `name` |
| `getElementsByTagName(name)` | возвращает коллекцию элементов с заданным именем тега `name` |
| `getElementsByClassName(name)` | возвращает коллекцию элементов с заданным именем класса `name` |
| `querySelector(selector)` | возвращает первый элемент, который соответствует заданному CSS-селектору |
| `querySelectorAll(selector)` | возвращает коллекцию всех элементов, которые соответствуют заданному CSS-селектору |

Полный список свойств и методов Element в [документации](https://developer.mozilla.org/en-US/docs/Web/API/Element).

#### HTMLElement

`HTMLElement` – это подтип класса Element, который расширяет его свойства и методы, предоставляя дополнительные свойства и методы, специфичные для HTML элементов. Ниже приведены наиболее распространенные свойства и методы класса HTMLElement:

| Свойство | Значение |
|:-----------------:|-------------------------------------------------------------------------------------------------------------------|
| `contentEditable` | возвращает или устанавливает значение, указывающее, может ли содержимое элемента быть редактируемым пользователем |
| `draggable` | возвращает или устанавливает значение, указывающее, может ли элемент быть перетаскиваемым пользователем |
| `hidden` | возвращает или устанавливает значение, указывающее, должен ли элемент быть скрытым отображением |
| `hidden` | возвращает или устанавливает значение, указывающее, должен ли элемент быть скрытым отображением |
| `offsetHeight` | возвращает высоту элемента включая высоту границы |
| `offsetWidth` | возвращает ширину элемента включая ширину границы |
| `scrollHeight` | возвращает высоту содержимого элемента включая содержимое, которое не отображается в окне просмотра |
| `scrollWidth` | возвращает ширину содержимого элемента включая содержимое, которое не отображается в окне просмотра |

| Метод | Описание |
|:---------:|-----------------------------------|
| `click()` | имитирует щелчок мыши на элементе |
| `focus()` | устанавливает фокус на элементе |
| `blur()` | снимает фокус с элемента |

Полный список свойств и методов HTMLElement в [документации](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement).

#### Document

Объект `Document` представляет собой HTML или XML документ и предоставляет доступ к элементам и свойствам документа. Ниже приведены наиболее распространенные свойства, методы и коллекции объекта `Document`.

| Коллекция | Описание |
|:---------:|--------------------------------------------------------|
| `images` | коллекция изображений (объектов Image) на странице |
| `links` | коллекция ссылок (объектов Link) на странице |
| `forms` | коллекция форм (объектов Form) на странице |
| `scripts` | коллекция скриптов на странице |
| `anchors` | коллекция якорных ссылок (объектов Anchor) на странице |
| `all` | коллекция всех элементов на странице |

| Свойство | Значение |
|:-----------------:|------------------------------------------------------------------------------------------|
| `cookie` | возвращает или устанавливает значение cookie для документа |
| `defaultView` | возвращает объект `window`, связанный с документом |
| `documentElement` | возвращает корневой элемент документа |
| `domain` | возвращает или устанавливает доменное имя сервера, который отдает документ |
| `location` | возвращает объект `Location`, который содержит информацию о текущем URL-адресе документа |
| `referrer` | возвращает URL-адрес документа, который вызвал текущий документ |
| `head` | возвращает элемент `` документа |
| `title` | возвращает или устанавливает значение тега `` документа |
| `body` | возвращает элемент `` документа |

| Метод | Описание |
|:-----------------------------------:|------------------------------------------------------------------------------------|
| `appendChild(node)` | добавляет узел в конец списка дочерних элементов указанного родительского элемента |
| `createElement(tagName)` | создает новый элемент с указанным именем тега |
| `createTextNode(text)` | создает новый текстовый узел с указанным текстом |
| `getElementById(id)` | возвращает элемент с указанным идентификатором |
| `getElementsByTagName(tagName)` | возвращает коллекцию элементов с заданным именем тега |
| `getElementsByClassName(className)` | возвращает коллекцию элементов с заданным именем класса |
| `replaceChild(newNode, oldNode)` | заменяет дочерний элемент `oldNode` на `newNode` |
| `removeChild(node)` | удаляет узел из списка дочерних элементов указанного родительского элемента |

Полный список свойств и методов Document в [документации](https://developer.mozilla.org/en-US/docs/Web/API/Document).

#### Примеры свойств и методов узлов DOM

Создание элемента и текстовых узлов

```js
// Создание нового элемента


const p = document.createElement('p')
// Создание текстового узла
const txt = document.createTextNode('Это новый параграф в конце')
// Вставка в элемент
p.appendChild(txt)
// Вставить в конец элемента body
document.body.appendChild(e)
```

Способ с `insertBefore()`

```js
const p = document.createElement('p')
p.appendChild(document.createTextNode('Это новый параграф вначале'))
// Второй аргумент – перед каким элементом
document.body.insertBefore(e, document.body.firstChild)
```

Создание фрагмента

```js
const p = document.createElement('p')
p.textContent = '... fragment text ...'

// Создание фрагмента
const fragment = document.createDocumentFragment()
// Вставка в фрагмент
fragment.appendChild(p)
// Вставка клонированного фрагмента в



const div = document.getElementById('div')
// Параметр true скопирует элемент с содержимым
div.appendChild(fragment.cloneNode(true))
```

Удаление элементов

```js
// Последний дочерний элемент в секции body
const lastElement = document.body.lastChild
// Фильтруем текстовые узлы
while (lastElement.nodeType == 3)
// Присвоение предыдущего соседнего узла
lastElement = lastElement.previousSibling

// Если в body есть дочерние узлы
if (document.body.hasChildNodes())
// Удаляем последний дочерний элемент
document.body.removeChild(lastElement)
```

Модифицирование элемента

```js
// Первыый попавшийся элемент h1
const e = document.getElementsByTagName('h1')[0]
// Изменение стилей
e.style.font = '28px Impact, Tahoma, Segoe, monospace'
e.style.color = '#45D'
e.style.textShadow = '#A2C 0 0 5px'
e.innerHTML = 'innerText' // Вставит как код HTML
e.childNodes[0].nodeValue = 'innerText' // Вставит как текст
```

Манипуляция атрибутами элемента

```js
// Формируем массив абзацев
const paragraphes = document.getElementsByTagName('p')

// Смена атрибута align на противоположный
for (let i in paragraphes) {
if (paragraphes[i].getAttribute('align') == 'right')
paragraphes[i].setAttribute('align', 'left')
else if (paragraphes[i].getAttribute('align') == 'left')
paragraphes[i].setAttribute('align', 'right')
else
paragraphes[i].removeAttribute('align') // Пример удаления
}
```

## События

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

### Обработчики событий

Для обработки событий JavaScript использует слушатели событий (Event Listeners) – это функции JavaScript, которые вызываются в ответ на определённое действие. Эти функции могут быть назначены различным HTML-элементам либо другим состояниям веб-страницы. Пример обработчика события `onlclik` (одинарный щелчок мыши):

```html
Нажми меня
```

```js
// Получаем ссылку на кнопку
const button = document.querySelector('btn')

// Создаем функцию-обработчик события onclick
function handleClick() {
console.log('Кнопка была нажата!')
}

// Регистрируем обработчик события onclick для кнопки
button.onclick = handleClick
```

Также обработчик события может быть назначен с помощью HTML-атрибута, например атрибутом `onclick`.

### Объект события

JavaScript создает объект события (Event) в момент его возникновения. Этот объект передается в обработчик события и содержит всю информацию о событии, например, координаты мыши, нажатые клавиши и т.д.

Создание объекта события:

```js
element.addEventListener('click', function(event) {
// event – объект события
})
```

В примере выше `event` и есть объект события, который будет передан обработчику события `click`. Название события `event` может быть любым каким зададите.

Свойства объекта события:

| Свойство | Значение |
|:---------------------------:|------------------------------------------------------------|
| `event.type` | тип события, например, `click`, `keydown` и т.д. |
| `event.target` | элемент, на котором произошло событие |
| `event.currentTarget` | элемент, на котором был зарегистрирован обработчик события |
| `event.keyCode` | (устарел) код клавиши, нажатой при событии клавиатуры. |
| `event.pageX`/`event.pageY` | координаты указателя мыши относительно документа |

Свойства объекта события могут варьироваться в зависимости от типа события. Полный их список доступен в [документации](https://developer.mozilla.org/en-US/docs/Web/API/Event).

### Отмена действия по умолчанию

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

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

```js
element.addEventListener('submit', function(event) {
// Некоторые проверки и логика...
if (неудовлетворяет условию) {
return false // Отменяет отправку формы
}
})
```

Другой способ заключается в вызов метода `preventDefault()` в обработчике события.

Методы объекта события

| Метод | Описание |
|:----------------------------:|-----------------------------------------------------------------------------------------------------------------------|
| `preventDefault()` | предотвращает стандартное действие, связанное с событием |
| `stopPropagation()` | останавливает дальнейшее распространение события по дереву элементов. Предотвращает всплытие события |
| `stopImmediatePropagation()` | останавливает дальнейшее распространение события и предотвращает вызов других обработчиков событий для этого элемента |

### Распространенные типы событий

События мыши

| Событие | Описание |
|:-----------:|-----------------------------------------------------------|
| `click` | происходит при клике на элементе |
| `dblclick` | при двойном клике на элементе |
| `mousedown` | при нажатии кнопки мыши на элементе |
| `mouseup` | при отпускании кнопки мыши на элементе |
| `mousemove` | при перемещении мыши над элементом |
| `mouseover` | происходит, когда курсор мыши пересекает границу элемента |
| `mouseout` | когда курсор мыши покидает границу элемента |

События клавиатуры

| Событие | Описание |
|:----------:|----------------------------------------------|
| `keydown` | происходит при нажатии клавиши на клавиатуре |
| `keyup` | при отпускании клавиши на клавиатуре |
| `keypress` | клавиша нажата и отпущена |

События формы

| Событие | Описание |
|:--------:|-----------------------------------------------------------------------|
| `submit` | происходит при отправке формы |
| `input` | при изменении значения элемента ввода (`input`, `textarea`, `select`) |
| `change` | при изменении значения элемента формы (`input`, `select`, `textarea`) |

События окна и документа

| Событие | Описание |
|:--------:|-----------------------------------------------------------|
| `load` | при полной загрузке веб-страницы или ресурса |
| `unload` | перед закрытием страницы или переходом на другую страницу |
| `resize` | при изменении размеров окна браузера |
| `scroll` | при прокрутке содержимого страницы |

События фокуса

| Событие | Описание |
|:-------:|--------------------------------|
| `focus` | при получении элементом фокуса |
| `blur` | при потере элементом фокуса |

События навигации

| Событие | Описание |
|:------------:|----------------------------------------------------------------------------------------------|
| `hashchange` | при изменении URL-фрагмента (хэша) в адресной строке браузера |
| `popstate` | при изменении истории переходов (например, при нажатии кнопок "назад" и "вперед" в браузере) |