0% нашли этот документ полезным (0 голосов)
694 просмотров

REDEV JavaScript

Учебник по JavaScript охватывает основы языка, включая переменные, типы данных, операторы и функции, а также более сложные темы, такие как асинхронный код и объектно-ориентированное программирование. Он предоставляет информацию о том, как запускать код, и рекомендует использовать редакторы кода и IDE, такие как VSCode и WebStorm. В документе также содержится статистика использования JavaScript в 2023 году, подчеркивающая его популярность и универсальность.

Загружено:

ilianardan
Авторское право
© © All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
0% нашли этот документ полезным (0 голосов)
694 просмотров

REDEV JavaScript

Учебник по JavaScript охватывает основы языка, включая переменные, типы данных, операторы и функции, а также более сложные темы, такие как асинхронный код и объектно-ориентированное программирование. Он предоставляет информацию о том, как запускать код, и рекомендует использовать редакторы кода и IDE, такие как VSCode и WebStorm. В документе также содержится статистика использования JavaScript в 2023 году, подчеркивающая его популярность и универсальность.

Загружено:

ilianardan
Авторское право
© © All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
Вы находитесь на странице: 1/ 220

📗

Учебник по JavaScript

󾠷 Перед стартом

🏅 0. Про JavaScript
🆕 0. Как запускать код?
󾠮 1-й чек-лист

👽 1.1. Переменные
🌀 1.2. Типы данных
🎴 1.3. Операторы
📓 1.4. Циклы и Switch
🏆 1.5. Функции
󾠯 2-й чек-лист

🕣 2.1. Числа
🌙 2.2. Строки
🚥 2.3. Объекты. Основы
🤯 2.4 Объекты. Углубиться

Учебник по JavaScript 1
󾠰 3-й чек-лист

🛎 3.1. Массивы
🏕 3.2. Методы массивов
󾠱 4-й чек-лист

☔ 4.1. ДП + spread
🧵 4.2. JSON
⚠ 4.3. try…catch...finally
🪧 4.4. Прототип
🗓 4.5. Дата и время
💥 4.6. Коллекции. Map и Set
➿ 4.7. Замыкание. Рекурсия. Каррирование
󾠲 5-й чек-лист

🏛 5.1. class
🪧 5.2. ООП в JavaScript
󾠳 6-й чек-лист

🔄 6.1. Асинхронный код


🔙 6.2. callback

Учебник по JavaScript 2
6.3. Promise

🔄 6.4. async/await
🔂 6.5. Event Loop
🌐 6.6. HTTP (fetch)

Учебник по JavaScript 3
🏅
0. Про JavaScript
JavaScript - это язык программирования, который используется для создания
динамических веб-страниц. Он может быть использован для добавления
интерактивности и функциональности на сайт, включая обработку событий,
манипуляцию элементами на странице, и многое другое. JavaScript также может
быть использован для создания веб-приложений , мобильных приложений и
десктопных приложений. В 2023 году он был самым популярным языком
программирования, используемым в 70% всех проектов.

Статистика языков программирования по


использованию за 2023 год
Данные, собранные в 2023 году, показывают, что JavaScript был самым
популярным языком программирования в этом году. Он использовался в {70%}
проектов, что делает его языком номер один в рейтинге.

На втором месте находится язык Python, который использовался в {15%} проектов,


за ним следуют Java ({10%}), C++ ({3%}), Ruby ({1%}) и другие языки ({1%}).
JavaScript продолжает расти в популярности благодаря своей широкой
функциональности и универсальности. Он используется для создания веб-
приложений (их мы и будем учиться делать), мобильных приложений и даже
настольных приложений.

0. Про JavaScript 1
История
JavaScript был создан в 1995 году Бренданом Айком в компании Netscape
Communications Corporation. Он был разработан как язык программирования для
обработки веб-страниц на стороне клиента, то есть на компьютере пользователя.
Изначально он назывался Mocha , затем LiveScript , а в конечном итоге был
переименован в JavaScript .
Название JavaScript было выбрано для создания ассоциации с Java , который на
тот момент был очень популярен. Однако, несмотря на сходство в названии,
JavaScript и Java являются разными языками программирования с разной

синтаксической структурой и различными возможностями.

0. Про JavaScript 2
Текущая версия JavaScript - это ECMAScript 2021 (ES2021), которая была
выпущена в июне 2021 года.

Желаю тебе удачного обучения на курсе!


JavaScript - отличный язык программирования, и я уверен, что ты сможешь многое
достичь в своей карьере, изучая его. Let’s goooooooo!

🆕 0. Как запускать код?

0. Про JavaScript 3
🆕
0. Как запускать код?
Существует множество онлайн редакторов для JavaScript, которые могут быть
использованы для написания JavaScript кода. Некоторые из наиболее популярных
онлайн редакторов для JavaScript:

1. CodePen (https://codepen.io/)

2. JSFiddle (https://jsfiddle.net/)

3. Repl.it (https://repl.it/)

4. JS Bin (https://jsbin.com/)

5. Glitch (https://glitch.com/)

6. StackBlitz (https://stackblitz.com/)

Каждый из этих редакторов имеет свои уникальные функции и возможности. Они


обеспечивают множество средств для отладки, тестирования и оптимизации кода.
Эти редакторы также предлагают поддержку популярных библиотек и
фреймворков JavaScript, таких как React, Vue.js, Angular и других.
Но лучше писать код сразу в IDE*

Существует множество IDE (Integrated Development Environment) для разработки


программного обеспечения на JavaScript.

1. VSCode - Visual Studio Code бесплатная IDE с открытым исходным кодом от


Microsoft. Она имеет множество расширений для JavaScript, а также
интегрированный отладчик.

2. WebStorm - разработанная компанией JetBrains. Она предлагает широкий


набор инструментов для разработки, отладки и тестирования JavaScript кода.

Я рекомендую писать сразу в VSCode или WebStorm чтобы привыкать к работе с ним.
Я использую VSCode.

0. Как запускать код? 1


Как же запустить код?

Способ #1
Для запуска JavaScript кода в VSCode необходимо установить расширение Code

Runner . Это можно сделать следующим образом:

1. Открой VSCode .

2. Нажми на кнопку Extensions в левой боковой панели.

3. Введи Code Runner в поле поиска и нажми Enter .

4. Установи расширение Code Runner

5. После установки, в твоем коде (index.js), выберите код, который хочешь


запустить.

6. Нажми Ctrl + Alt + N или нажмите на кнопку Play в правом верхнем углу
редактора.

7. В результате, увидишь вывод кода в терминале.

0. Как запускать код? 2


Надеюсь, это поможет запустить JavaScript код в VSCode !

Способ #2
Для запуска JavaScript кода в VSCode необходимо установить node.js.

1. Открой VSCode .

2. В верхнем меню нужно создать новый терминал

3. В терминале запустить код (node + название файла)

0. Как запускать код? 3


Код может не запуститься. Проверь в первую очередь установлен ли node.js
командой
node -v

Если увидишь версию, как в примере выше, то все отлично. Можно работать!

Видео:
https://youtu.be/bAcu9ymOoRc

0. Как запускать код? 4


👽
1.1. Переменные

Что же такое переменная?


Переменная - это поименованное хранилище для данных. 🤨
Океееей, тебе может не понравится слово поименованное. Тогда еще один
вариант.
Переменная - это контейнер, который хранит какое-то значение. Например,
контейнер для хранения количества яблок в корзине.

1.1. Переменные 1
let appleCount = 6;
console.log(appleCount); //выводит 6

Значение переменной может быть любым - числом, строкой, объектом, массивом


и т.д.

Схема создания переменной может быть такой:

ключевоеСлово имяПеременной = значениеПеременной;

let firstName = "Pavel";

Как объявить переменную?


В JavaScript существует 3 способа объявить переменную:

let

const

var

Первые 2 способа являются современными, а var устарел. В новом коде не


используется. В старых примерах ты будешь его еще видеть.

let num = 5;
const str = "Redev";
var isAdmin = true;

Важность регистра и осознанное именование


JavaScript - регистрозависимый язык, что означает, что регистр букв в названиях
переменных, функций и т.д. имеет значение. Например, переменная "myVariable" и
"myvariable" считаются разными.

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

1.1. Переменные 2
Осознанное именование переменных в JavaScript является важным аспектом
программирования, поскольку оно помогает сделать код более читаемым и
понятным.

Когда переменные имеют осмысленные имена, которые соответствуют их функции


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

const a = 25; //не понятно что означает а!


const age = 25; // понятно, речь идет про возраст

camelCase и snake_case

1.1. Переменные 3
Имена переменных могут состоять из нескольких слов! Что делать в таком
случае? Как именовать переменные? Вот ответ

CamelCase и snake_case - это два стиля написания имен переменных в


JavaScript.
CamelCase - это когда каждое слово в имени переменной начинается с заглавной
буквы, но без пробелов между словами. Например: "myVariableName". Этот
стиль принято использовать в большинстве случаев, он легко читается и
понимается.
Snake_case - это когда каждое слово в имени переменной разделено
подчеркиванием. Например: "my_variable_name".

Оба стиля допустимы в JavaScript, но рекомендуется использовать camelCase, так


как этот стиль считается более стандартным и принятым в основном сообществе
разработчиков.

Отличия let и const


Переменную, объявленную с помощью let можно менять. Например, вот так

let num = 5;
num = 6;// значение переменной num изменится

Переменную с const нельзя изменять.

const num = 5;
num = 6; // будет ошибка

По этой же логике константу нельзя создавать пустой.

const num;// будет ошибка


let num;// значение будет undefined

Отличия let и var


1. Переменную с var можно объявлять повторно с таким же именем.

1.1. Переменные 4
var num = 10;
var num = 15;
console.log(num);// переменная просто перезапишется и будет 15

let num = 10;


let num = 15;
console.log(num);// с let будет ошибка ибо нельзя
// создавать переменные с одинаковым именем

2. Область видимости.
У let она блочная, а у var функциональная. То есть let ограничивается
ЛЮБЫМИ ФИГУРНЫМИ скобками, а var только функцией.

{
let num = 1;
console.log(num); // тут переменная будет видна
}
console.log(num); // тут уже будет ошибка
------------------------------------------------------
{
var num = 1;
console.log(num); // тут переменная будет видна
}
console.log(num); // и тут тоже переменная будет видна
------------------------------------------------------
function func(){
var num = 1;
console.log(num); // тут переменная будет видна
}
console.log(num); // тут уже будет ошибка

3. Hoisting.
Hoisting - это механизм, который позволяет JavaScript поднимать объявления
переменных в начало текущего контекста выполнения. В результате этого
переменные могут использоваться до того, как они объявлены в коде.
ВАЖНО: при этом значение ее будет undefined (пустота)!
Если же попробовать достучаться до объявленной переменной с помощью let,
то будет ошибка.

console.log(num);// undefined
var num = 10;

1.1. Переменные 5
console.log(num);// ошибка
let num = 10;

Как именовать переменные?


Первый символ не может быть цифрой.

Имя переменной должно содержать только буквы, цифры или символы $ и _.

let age = 25; // ошибки не будет


let age123 = 25; // ошибки не будет
let 123age = 25; // ошибка
let 15 = 25; // ошибка
let name_abc = 25; // ошибки не будет
let name-abc = 25; // ошибка

В JavaScript есть несколько зарезервированных слов, которые не могут


использоваться в качестве имен переменных:

var , let , const - слова, которые используются для объявления переменных;

function - слово, которое используется для объявления функций;

class - слово, которое используется для объявления классов;

break , case , catch , continue , debugger , default , ,


delete , do , else , finally for ,
in , instanceof , new , return , switch , this , throw , try , typeof , void , while , with

- слова, которые используются в синтаксисе языка javascript;

, else , true , false , null , undefined - слова, которые используются для


if

логических операций над данными.

Важно следовать стандартам названия переменных и избегать использования


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

Итого:
1. Есть 3 способа объявить переменную ( let , const , var )

2. C const - переменная которую нельзя изменить.

3. Регистр важен!

1.1. Переменные 6
4. Лучше использовать camelCase чем snake_case

5. Для собеседования важно знать 3 отличия let и var ! Заучивай

Еще материал по теме:


1. https://developer.mozilla.org/ru/docs/Learn/JavaScript/First_steps/Variables

Задания
1. Создай две переменные с именами name и age и присвой им любые значения.

2. Создай переменную nameAge и присвой ей значение, равное объединению (+)


значений переменных name и age.

3. Выведи переменную nameAge в консоль.

4. Что выведет в консоль?

const studentName = "John";


studentName = "Paul";
console.log(studentName); //?

var age = 25;


var age = 26;
console.log(age);//?

let age = 25;


let age = 26;
console.log(age);//?

let age = 25;


console.log(age);//?
age = 30;
console.log(age);//?

console.log(age);//?
let age = 25;

1.1. Переменные 7
console.log(age);//?
var age = 25;

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/7beAZaxvStz4zFnB6

Переход к следующей главе

🌀 1.2. Типы данных

1.1. Переменные 8
🌀
1.2. Типы данных
В JavaScript существует 8 типов данных. Про каждый подробно мы поговорим
в следующих главах, а пока их надо выучить:

1. number - число (целые и дробные числа, NaN, Infinity,-Infinity);

2. string - строка (все строки, например, мое имя “Павел” );

3. boolean - булевое значение (true или false);

4. null - пустота ( явно заданное значение, которое означает "ничего”);

5. undefined- неопределённость (присваивается переменной, которая не имеет


значения);

6. symbol - символ (для создания уникальных идентификаторов);

7. bigInt- биг инт - большое число (для работы с очень большими целыми
числами);

8. object - объект (представляет собой составной тип данных).

Все типы данных делятся на 2 категории: примитивы и объект. То есть 7 типов


данных являются примитивными и отдельная категория для объектов.

let num = 1; // number


let str = "Redev"; // string
let isMan = true; // boolean
let empty = null; // *null
let abc; // undefined
let sym = Symbol(123); // symbol
let bigInt = 1n; // bigInt

let obj = {}; // object

Оператор typeof

1.2. Типы данных 1


В JavaScript существует оператор, который помогает определить тип данных
переменной.

Синтаксис прост: typeof 5 или typeof (5). Как кому удобно.


Надо разобраться с тем, что же возвращает оператор typeof. Он возвращает
СТРОКУ с типом данных аргумента (переменной).

Вот тебе пример Внимательно просмотри их:

let num = 1;
typeof num; // "number"

let str = "Redev";


typeof str; // "string"

let isMan = true;


typeof isMan; // "boolean"

let empty = null;


typeof empty; // * "object" !!!

let abc;
typeof abc; // "undefined"

let sym = Symbol(123);


typeof sym; // "symbol"

let bigInt = 1n;


typeof bigInt; // "bigInt"

let obj = {};


typeof obj; // "object"

let arr = [];


typeof arr; // "object" !!!

function func(){}
typeof func; // "function" !!!

ИСКЛЮЧЕНИЕ. typeof null не вернет null. Будет object.


Почему? Это просто ошибка в JavaScript с первой его версии.
Эту ошибку не фиксят по причине обратной совместимости.

1.2. Типы данных 2


Уже слишком много кода учитывает эту ошибку и её
исправление приведет к куче багов 😭
Обращаю внимание на то, ЧТО ВОЗВРАЩАЕТ typeof.

Он возвращает СТРОКУ с типом данных аргумента (переменной).

let age = 25;


const isMan = true;

console.log(typeof typeof age); // "string"


console.log(typeof typeof isMan); // "string"

Почему “string” ?
Потому что, typeof age вернет “number” , а typeof “number” вернет “string”.
Потому что, typeof isMan вернет “boolean” , а typeof “boolean” вернет “string”.

Еще материал по теме:


1. https://developer.mozilla.org/ru/docs/Learn/JavaScript/First_steps/Variables

2. https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/typeof

Задания
1. Чему будет равно выражение typeof -5; ?

2. Чему будет равно выражение typeof false; ?

3. Чему будет равно выражение typeof "1"; ?

4. Чему будет равно выражение typeof null; ?

5. Чему будет равно выражение typeof typeof 5; ? и почему?

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и

1.2. Типы данных 3


остальных студентов!
Заполни форму
https://forms.gle/C6qU1sBWjLnSQCDf6

Переход к следующей главе

🎴 1.3. Операторы

1.2. Типы данных 4


🎴
1.3. Операторы
В этой главе мы разберем всё про операторы.

Выделяется несколько групп операторов:

1. Математические

2. Сравнения

3. Условные

4. Логические

Надо разобраться, что такое операнд и оператор, прежде чем идти дальше!
В JavaScript операнд - это значение, которое обрабатывается оператором.
Операнды могут быть любым типом данных, например, числами, строками, объектами
и т.д.
Например, в выражении 5 + 2 , 5 и 2 являются операндами, а + является
оператором.
Каждый оператор имеет свой синтаксис и правила использования, и результат их
выполнения может быть разным в зависимости от типа операндов.

Математические
+ // плюс
- // минус
* // умножить
/ // разделить
% // остаток от деления
** // возведение в степень

Если с первыми четырьмя все понятно (если нет, то ты зря купил курс 🤔 ), то про
два последних поговорим.

Остаток от деления (%)

1.3. Операторы 1
% - это остаток от деления и он возвращает остаток от целочисленного деления. Тихо
тихо…сейчас поясню.

Возьмем пример console.log(5%2). В консоли увидим 1, так как 5 можно расписать как
2+2+1, двойки сократили, потому что берем %2 и остается 1.

Давай еще примеры:

console.log(7%3);//1 (3+3+1 остаток 1)


console.log(5%3);//2 (3+2 остаток 2)
console.log(6%3);//0 (3+3 остаток 0)
console.log(6%2);//0 (2+2+2 остаток 0)
console.log(14%5);//4 (5+5+4 остаток 4)

Возведение в степень (**)


** - это оператор возведения в степень. Что возводим и в какую степень.
2**3 - два возводим в третью степень (2 * 2 * 2) и это будет 8.

console.log(2**2);//4 (2*2)
console.log(5**3);//125 (5*5*5)
console.log(3**3);//27 (3*3*3)

Операторы сравнения
> // больше
< // меньше
>= // больше или равно
<= // меньше или равно
== // равно
=== // строгое равно
!= // не равно
!== // строгое не равно

"Запомни, что в JavaScript равно - это не символ математического


"равно" =, а символ "двойное ровно" == или "тройное равно" ===

Тут встает вопрос, а какая же разница между == и ===?

1.3. Операторы 2
Разница простая: строгое равно (===) учитывает типы данных при сравнении, а не
строгое равно (==) приводит все к одному типу (числу).

Давай смотреть на примерах

console.log(5===5);// true, потому что у обоих тип данных number


console.log(5==="5");// false, потому что один number, второй string

console.log(5==5);// true, потому что пять равно пять


console.log(5=="5");// true, потому что приведутся к числу и "5" станет числом 5

console.log(5===true);// false, потому что разные типы данных (number и boolean)


console.log(5==true);// false, потому что true приведется к числу и станет 1, а 5 не равно 1

"Не равно" (not equal) в JavaScript обозначается с помощью оператора != . Он


сравнивает два значения и возвращает true, если они не равны, и false, если они
равны.
Однако, существует также оператор !== , который проверяет не только неравенство
значений, но и равенство типов. Он возвращает true , если значения или типы не
равны.

Примеры с использованием оператора "не равно" в JavaScript:

1. Оператор != :

let x = 5;
let y = "5";
console.log(x != y); // false

let a = 10;
let b = 20;
console.log(a != b); // true

2. Оператор !== :

let x = 5;
let y = "5";
console.log(x !== y); // true

let a = 10;
let b = "10";
console.log(a !== b); // true

let a = 5;

1.3. Операторы 3
let b = 5;
console.log(a !== b); // false

Все операторы сравнения возвращают boolean (true или false).

Условное ветвление: if, '? :'


Очень часто нам нужно сделать какие-то действия в зависимости от условия.
Как раз в этом нам и поможет конструкция if else и тернарный оператор (? :)

if(условие){
//тело
} else {
//тело
}

const a = 5;
if(a>3){
console.log("верно");
} else {
console.log("не верно");
}

Сейчас прочту эту конструкцию.

“Если а больше 3, то выведем в консоль “верно”, иначе выведем в консоль “не


верно”.”

Если..то..иначе - как-то так это читается.

Тернарный оператор работает точно так же и читается точно так же, просто
синтаксис другой. Смотри

условие ? выражение1 : выражение2

const a = 5;
a>3 ? console.log("верно") : console.log("не верно");

Результат будет такой же.


Какое отличие if else от тернарного оператора?
У if else блок else необязательный, а у тернарного все 3 блока обязательные
(поэтому он и называется тернарный).

1.3. Операторы 4
Пояснение:

const name = "redev";


if(name === "redev"){
console.log(❤);
}
//можно написать без else

name === "redev" ? console.log(❤) // так нельяза писать, javascript будет ругаться
name === "redev" ? console.log(❤) : console.log(😭); // так правильно

Обращаю внимание на else if !!!!


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

let score = 75;

if (score >= 90) {


console.log('Отлично');
} else if (score >= 75) {
console.log('Хорошо');
} else if (score >= 60) {
console.log('Удовлетворительно');
} else {
console.log('Неудовлетворительно');
}

В приведенном выше примере мы проверяем значение переменной score . Если оно


больше или равно 90, то выводится сообщение ”Отлично”. Если значение больше или
равно 75, то выводится сообщение ”Хорошо” и т.д. Если ни одно из условий не
выполнено, то выполняется блок else и выводится сообщение
“Неудовлетворительно”.

Логические операторы
&& - и
|| - или
! - не

1.3. Операторы 5
! - не
Приводит к boolean и возвращает противоположное.

console.log(!true);// false
console.log(!false);// true
console.log(!5);// false. 5 приводит к boolean, это true, противоположное это false
console.log(!0);// true. 0 приводит к boolean, это false, противоположное это true
console.log(!"redev");// false. "redev" приводит к boolean, это true, противоположное это false
console.log(!"");// true. "" приводит к boolean, это false, противоположное это true

Надо запомнить false-значения:

0 - ноль

“” - пустая строка

undefined - пустота

null - пустота

NaN - не число

и сам false

Все остальное в JavaScript это true.

Двойное НЕ "!!" в JavaScript нужен для преобразования значения


в логический тип.

!!true = true
!!false = false
!!0 = false
!!1 = true
!!'' = false
!!'text' = true

Таким образом, "!!" может использоваться для преобразования значений, таких как
строки или числа и т.д. в логические значения.

&& - и
Возвращает первый false или последний true.

1.3. Операторы 6
console.log(2 && 0);// 0, потому что 2-true,а 0-false.
console.log(2 && 4);// 4, потому что 2-true,4-true и возвращает последний true.
console.log(0 && "redev");// 0, потому что 0-false и возвращает первый false.
console.log(3 && null && "redev");;// null

//3 - true
//null - false
//"redev" - true
Возвращает первый false то есть null

|| - или
Возвращает первый true или последний false.

console.log(2 || 0);// 2, потому что 2-true.


console.log(2 || 4);// 2, потому что 2-true,4-true и возвращает первый true.
console.log(0 || "redev");// "redev", потому что 0-false, а возвращает первый true. "redev"
console.log(3 || null || "redev");// 3, потому что 3-true.

//3 - true
//null - false
//"redev" - true
Возвращает первый true то есть 3

В JavaScript логические операторы имеют следующий порядок приоритета:

1. !

2. &&

3. ||

То есть сразу выполнится оператор “не” потом “и” , а далее “или” .


Если операторы имеют одинаковый приоритет, они выполняются слева направо.

?? - оператор нулевого слияния


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

let name = null;


let username = name ?? 'Guest';
console.log(username); // 'Guest'

1.3. Операторы 7
В приведенном выше примере, если переменная name имеет значение null или
undefined , то в переменную username будет записано значение по умолчанию 'Guest' .

let age = 0;
let userAge = age ?? 25;
console.log(userAge); // 0

ВНИМАНИЕ! 0 это не null.

В этом примере переменная age имеет значение 0 , которое является ненулевым (не
null или undefined), поэтому в переменную userAge будет записано это значение, а не
25.

Инкремент (++) и декремент (- -)


Инкремент и декремент являются унарными операторами в JavaScript, которые
используются для увеличения или уменьшения значения переменной на 1.

Инкремент (++) используется для увеличения значения переменной на 1:

let a = 5;
a++; // a теперь равно 6

Декремент (--) используется для уменьшения значения переменной на 1:

let a = 5;
a--; // a теперь равно 4

Инкремент и декремент могут быть использованы как префиксные, так и


постфиксные операторы.

Префиксный инкремент/декремент изменяет значение переменной и возвращает


измененное значение.

Постфиксный инкремент/декремент возвращает старое значение переменной, а


затем изменяет его.

let a = 5;
console.log(a++); // 5 - ПОСТфиксный

1.3. Операторы 8
console.log(a); // 6

let b = 5;
console.log(++b); // 6 - ПРЕфиксный
console.log(b); // 6

Инкремент и декремент часто используются в циклах.

Унарный, бинарный, тернарный


Унарный оператор применяется к одному операнду. Примеры унарных операторов
в JavaScript: +, -, !, typeof, ++,- - .

let age = "25";


console.log(+age); //25 - число

let count = 15;


console.log(++count); //16

Бинарный оператор применяется к двум операндам. Примеры бинарных


операторов в JavaScript: +, -, *, /, %, <, >, <=, >=, instanceof, in, ==, ===, !=, !== и
т.д.

let appleСost = 1;
let watermelonСost = 3;
console.log(appleСost + watermelonСost); //4

Тернарный оператор применяется к трем операндам. Этот оператор имеет


следующую структуру: (условие) ? значение1 : значение2 . Если условие истинно, то
возвращается значение1, если ложно, то возвращается значение2.

let age = 25;


let message = (age >= 18) ? "Доступ разрешен" : "Доступ запрещен";
console.log(message); // Выведет "Доступ разрешен"

В целом, в JavaScript операторы имеют разный приоритет и


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

1.3. Операторы 9
Про неявное и явное преобразование типов
в JS
JS имеет неявные и явные преобразования типов.

1. Неявные преобразования: происходят автоматически при операциях


вычисления, таких как арифметика или сравнение.

let result = 10 + "10"; // "1010"


let truthy = "foo" && true; // true
let falsy = "" || false; // false

2. Явные преобразования: нужно явно указать, как должен быть преобразован тип.
Это можно сделать с помощью функций parseInt() или Number() и т.д.

let number = Number("42"); // 42


let string = String(42); // "42"
let boolean = Boolean(1); // true

Основные преобразования типов в JS:


(как правило именно этими ты будешь пользоваться)

Boolean: !!x

String: x.toString()

Number: +x , parseInt(x) , parseFloat(x) , Number(x)

let integer = parseInt("10.34"); // 10


let float = parseFloat("10.34"); // 10.34

Важно помнить, что преобразование типов может привести к неожиданным


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

Еще материал по теме:


1. https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators

1.3. Операторы 10
Задания
1. Написать 3 любых примера с % и результат этого выражения (5%2 === 1).

2. Если переменная test равна true, то выведи “Верно”, иначе выведи “Неверно”.

3. Если переменная test не равна true, то выведи “Верно”, иначе выведи “Неверно”.

4. Если переменная a больше нуля и меньше 5-ти, то выведи “Верно“, иначе выведи
“Неверно“.

5. Если переменная a равна нулю или равна двум, то прибавь к ней 7, иначе
раздели ее на 3.

6. Если переменная a равна или меньше 1, а переменная b больше или равна 3, то


выведи сумму этих переменных, иначе выведи их разность.

7. Если переменная a больше 2-х и меньше 11-ти, или переменная b больше или
равна 6-ти и меньше 14-ти, то выведи “Верно”, в противном случае выведите
“Неверно”.

8. Написать алгоритм который проверит, попадает ли число в заданный диапазон.

9. Написать алгоритм, который выводит наименьшее из двух чисел.

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


отрицательным или равным нулю.

11. Что выведет в консоль и почему ?

let num = 5;
console.log(num == "5"); //?
console.log(num === "5"); //?
console.log(num == true); //?!

12. Что выведет в консоль и почему ?

console.log(5 && 3); //?


console.log(0 && 3); //?
console.log(5 || 3); //?
console.log(0 || 3); //?
console.log(0 || 3 && 6); //?
console.log(0 && 3 || 6); //?

13. Что выведет в консоль и почему ?

1.3. Операторы 11
let count = 6;
console.log(count++); //?
console.log(++count); //?
console.log(count++); //?
console.log(count); //?

14. Что выведет в консоль и почему ?

let count = 4;
console.log(count--); //?
console.log(count--); //?
console.log(count); //?
console.log(--count); //?

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы прислушаемся к
ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и остальных студентов!
Заполни форму
https://forms.gle/APa3mEA8Gq8dFJov9

Переход к следующей главе

📓 1.4. Циклы и Switch

1.3. Операторы 12
📓
1.4. Циклы и Switch
Циклы
Цикл в JavaScript - это конструкция, которая позволяет повторять определенный
блок кода несколько раз. Он полезен, когда тебе нужно выполнить однотипные
задачи многократно или обработать множество данных.

Циклы нужны, чтобы повторять одно действие определенное количество раз.


Запоминай это.

В JavaScript существует 3 цикла:

while

do while

for

Поговорим про циклы while и do-while в JavaScript!


Цикл while используется для повторения блока кода, пока выполняется
определенное условие. Проще говоря, цикл while позволяет выполнять код
многократно, пока условие истинно.

Вот пример цикла while, который выводит в консоль числа от 1 до 5:

let i = 1;
while (i <= 5) {
console.log(i);
i++;
}

В этом примере мы создали переменную i и установили ее равной 1. Затем мы


используем цикл while, чтобы проверять, что i не превышает 5, и выводим текущее
значение i в консоль. В конце каждой итерации цикла мы увеличиваем (i++)
значение i на 1.

1.4. Циклы и Switch 1


Цикл do-while похож на цикл while, но с одним отличием: он выполняет блок кода
один раз перед проверкой условия. То есть, даже если условие сразу
оказывается ложным, блок кода будет выполнен хотя бы один раз.

Разница while и do while в том, в какой момент проверяется условие.


В while сразу проверяется условие, а потом выполняется тело, а в do while сразу
выполнится тело и только потом проверится условие.

Что нам это дает?


В do while тело выполнится один раз обязательно. В while же нет, если условие
не выполняется (false).
Вот пример цикла do-while, который высчитывает факториал числа:

let number = 5;
let factorial = 1;
do {
factorial *= number;
number--;
} while (number > 0);
console.log('Факториал числа 5 равен', factorial);

В цикле do-while происходит умножение значения переменной factorial на


значение переменной number , а затем переменная number уменьшается на 1. Это
продолжается до тех пор, пока значение переменной number не станет меньше или
равным 0.

В результате, значение переменной factorial становится равным произведению


всех чисел от 1 до 5, то есть факториалу числа 5, а именно 120.

for
Собственно, это совершенно не важно, ибо циклы в чиcтом виде сейчас не
используются совершенно. Они нужны для понимания методов массива. Поэтому
запоминаем и разбираемся именно в цикле for. На него максимальный фокус.

Цикл for в JavaScript позволяет многократно выполнять некоторый блок кода с


определенными условиями.

Он состоит из четырех основных частей: инициализации переменной (начало),


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

1.4. Циклы и Switch 2


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

for (начало; условие; шаг){


тело цикла
}

Вот пример оптимизации с помощью цикла for :

// можно написать так, но не нужно. Для этого есть цикл for


console.log("Hello world1");
console.log("Hello world2");
console.log("Hello world3");

// так лучше
for (let i = 1; i<=3; i++){
console.log("Hello world"+i);
}

// или так (блок "начало" можно оставить пустым)


let i = 1;
for (; i<=3; i++){
console.log("Hello world"+i);
}

Пока блок условие будет true, цикл будет выполняться. Как только блок условие

будет false, цикл прекращает работу.

!!!именно в такой последовательности выполняются блоки!!!

начало → условие → тело → шаг →условие … и до тех пор пока условие true
Важно еще знать, что такое итерация.

Итерация - это одно прохождение цикла, одно прохождение условие → тело →

шаг .

Итерация - это процесс, в котором код выполняется несколько раз для решения
какой-либо задачи. Цикл for - это один из способов реализации итерации в
JavaScript.
В цикле for можно указать условие для количества итераций, которые должны
произойти. Например, можно написать цикл for для вывода чисел от 1 до 5:

1.4. Циклы и Switch 3


for (let i = 1; i <= 5; i++) {
console.log(i);
}

// Выведет:
// 1
// 2
// 3
// 4
// 5

В этом примере i является счетчиком, который начинается с 1 и


инкрементируется (увеличивается) на 1 каждый раз, после каждой итерации. Когда
i достигает 5, цикл прекращается.

Вроде изи!!! 😎 Обкатаешь ниже на задачах.


P.S Еще есть циклы for..in и for..of - это два цикла, которые можно
использовать в JavaScript для итерации по объектам или массивам. Про них
поговорим в следующих главах.

Break и continue
break и continue- это две ключевые команды, которые можно использовать внутри
цикла for для управления его поведением.

break- это команда, которая прерывает цикл for в любой момент, когда она
выполняется. Например, мы можем использовать break для прерывания цикла,
когда достигается определенное условие:

for (let i = 1; i <= 5; i++) {


if (i === 3) {
break;
}
console.log(i);
}

// Вывод:
// 1
// 2

- это команда, которая прерывает текущую итерацию цикла for , но


continue

продолжает выполнение цикла для следующей итерации. Например, мы можем

1.4. Циклы и Switch 4


использовать continue для пропуска определенных итераций:

for (let i = 1; i <= 5; i++) {


if (i % 2 === 0) {
continue;
}
console.log(i);
}

// Вывод:
// 1
// 3
// 5

В этом примере, когда i является четным числом, continue прерывает текущую


итерацию и переходит к следующей итерации.

Про эти 2 ключевых слова знать не обязательно, ибо все равно не будешь
это использовать на практике никогда

Switch
Switch в JavaScript используется для выполнения различных действий в
зависимости от значения выражения. Это позволяет удобно заменить
последовательность if-else-операторов, когда нам нужно сравнить одно значение с
различными вариантами.

Оператор switch принимает на вход выражение и последовательность case-


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

switch (expression) {
case value1:
//Здесь выполняются инструкции, если результат выражения равен value1
break;
case value2:
//Инструкции, соответствующие value2
break;
...

1.4. Циклы и Switch 5


case valueN:
//Инструкции, соответствующие значению valueN
//statementsN
break;
default:
//Здесь находятся инструкции, которые выполняются
//при отсутствии соответствующего значения
}

Разберем пример ниже


Есть 2 переменных a и b. В сумме они дают 3. Ищем case, подходящий под
условие в switch.

case 1 подходит? -нет.


case 3 подходит? -да, значит выполняем тело у case 3 до break.
Как только JavaScript встречает break , сразу останавливает работу switch.

const a = 1;
const b = 2;

switch (a+b) {
case 1:
console.log("Один")
break;
case 3:
console.log("Три")
break;
case 5:
console.log("Пять")
break;
default:
console.log("Ничего не совпало")
}

Разберем пример ниже


Eсли бы case 1 совпал и в нем нет break. Что бы тогда вывело?

Так как break нет, JavaScript пойдет выполнять код дальше, !!без каких-либо
проверок!! до следующего break (либо до конца кода switch).

То есть вывело бы "Один", "Три".

1.4. Циклы и Switch 6


const a = 1;

switch (a) {
case 1:
console.log("Один")
case 3:
console.log("Три")
break;
case 5:
console.log("Пять")
break;
default:
console.log("Ничего не совпало")
}

Разберем пример ниже

const str = "3";

switch (str) {
case 1:
console.log("Один")
case 3:
console.log("Три")
break;
default:
console.log("Ничего не совпало")
}

Тут выведет в консоль "Ничего не совпало", потому что str не совпало ни с одним
значением в case.
Как так? Ведь у нас есть case 3!!
Тут все просто: у них разные типы данных, а switch сравнивает СТРОГО (то
есть учитывает типы данных).

typeof "3" === "string"


typeof 3 === "number"

Задания
1. Выведи в консоль числа от 1 до 100.

1.4. Циклы и Switch 7


2. Выведи в консоль числа от 11 до 33.

3. Выведи в консоль все целые числа от 10 до 1 в обратном порядке:

4. Выведи столбец четных чисел в промежутке от 0 до 100.

5. Выведи в консоль таблицу умножения на 5.

5 x 1 = 5
5 x 2 = 10

5 x 10 = 50

6. С помощью цикла найди сумму чисел от 1 до 100.

7. Напиши switch, который проверит значение переменной a и выведет в


консоль соответствующее сообщение а равен 1 , а равен 2 , а равен 3 , а не равен

ничего из перечисленого .

8. Напиши switch который принимает на вход число от 1 до 7 и выводит в


консоль соответствующий день недели (1 - понедельник, 2 - вторник и т.д.):

9. Напиши switch , который принимает на вход символ латинского алфавита и


выводит в консоль его порядковый номер (A - 1, B - 2 и т.д.)

10. Напиши switch , который принимает на вход число от 1 до 12 и выводит в


консоль соответствующее ему время года (зима, лето, осень, весна)
(потренируй объедине́ние case-ов)

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


ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и остальных
студентов!
Заполни форму
https://forms.gle/MmynFDue6nrTPjLt7

Переход к следующей главе

🏆 1.5. Функции

1.4. Циклы и Switch 8


🏆
1.5. Функции
Самое важное. То с чем придется работать every day!

Функция — это мини-программа внутри твоей основной программы, которая делает


какую-то одну понятную вещь. Ты однажды описываешь, что это за вещь, а потом
ссылаешься на это описание.

Зачем нужны функции?


Функции позволяют писать код, который можно повторно использовать
(переиспользовать), улучшая читаемость и поддерживаемость кода.
Пример из жизни — готовим яичницу 🍳
Этот процесс можно описать следующим алгоритмом действий:

1. Берем сковороду.

2. Ставим на плиту.

3. Включаем плиту.

4. Подходим к холодильнику.

5. Открываем холодильник.

6. Берем яичко 🥚
7. Закрываем холодильник.

8. Подходим к плите.

9. Разбиваем яичко.

10. Ждемс 🤤
Описание приготовления яичка условное, но в целом алгоритм может быть описан именно
так. Теперь, когда вам нужно будет в коде описывать приготовление яичка, вам придется
описывать весь этот алгоритм из «10 строк кода». Чтобы этого не делать, можно поступить
проще — оформить все эти действия в функцию “cookEggs” и вызывать ее, когда это
будет нужно.
Мы выяснили, что функция в программировании — это возможность вызвать алгоритм
каких-то действий. То есть функция “cookEggs” — это возможность вызвать алгоритм

1.5. Функции 1
«приготовления яичка», который состоит из множества действий.

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

Например:

function calculateSum(a, b) {
return a + b;
}

function getUserName() {
return "Павел Гуцу";
}

function createList() {
// твой код
}

Обрати внимание, что имена функций должны быть осмысленными и


краткими, например, вместо "calculateTheSumOfTwoNumbers" лучше
использовать "calculateSum".

В JavaScript есть общепринятые префиксы, которые могут использоваться в именовании


функций:

get - используется для функций, возвращающих значение, например, getUserName ;

set - используется для функций, изменяющих значение, например, setUserName ;

calculate - используется для функций, выполняющих вычисление, например,


calculateSum ;

create - используется для функций, создающих новый объект или структуру данных,
например, createList ;

update - используется для функций, обновляющих существующие данные, например,


updateUserInformation ;

… и таких много.

Однако это необязательные правила, и использование префиксов зависит от


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

1.5. Функции 2
Виды функций
Есть 3 вида функций:

Function Declaration

Function Expression

Arrow Function

Function Declaration (FD)


Давай охарактеризуем функцию sum ниже.
Имя функции : sum
Параметры : a, b
Возвращает : сумму a и b

function имяФункции(параметры){
тело функции
}

function sum(a,b){
return a+b;
}

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

Вызывается функция по ее имени с круглыми скобками.

function sum(a,b){
return a+b;
}
sum(2,3);//5
sum(3,3);//6
sum(0,6);//6
sum(-10,15);//5

В качестве аргумента функции можно передавать все что угодно, не только числа;

function func (param){


console.log(param);
}
function abc (a){
console.log(a);
}

1.5. Функции 3
func(1);//number
func("Redev");//string
func(true);//boolean
func(null);//null
func({name:"Pasha"});//object
func([1,2,3]);//array
func(abc);//function

Function Expression (FE)


Чтобы написать FE, нужно взять FD и имя функции вынести в переменную.
Запоминай синтаксис.

function sum(a,b){ //FD


return a+b;
}

const sum = function (a,b){ //FE


return a+b;
}

Работает FE почти так же, как и FD, но есть одно отличие в Hoisting-e.
Функцию, объявленную как FD, можно вызвать до ее объявления! Вот пример

console.log(sumFD(1,2)) //3
function sumFD(a,b){ //FD
return a+b;
}

console.log(sumFE(1,2)) //будет ошибка


const sumFE = function (a,b){ //FE
return a+b;
}

Arrow Function (стрелочная функция)


Запомнить синтаксис просто. Берем FE и убираем длинное слово function , а так же
ставим стрелку (функция поэтому и называется стрелочная).

const sumFE = function (a,b){ //FE


return a+b;
}

const sumFE = (a,b) => { // Arrow Function


return a+b;
}

1.5. Функции 4
Существует короткая запись Arrow Function. В короткой записи не нужно писать слово

return , так как стрелка ( ) выполняет роль return. Оба варианта работают одинаково.

Сравни

const sumFE = (a,b) =>{


return a+b;
}

const sumFE = (a,b) => a+b;

В каком случае можно сокращать функцию?


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

const sumFE = (a,b) =>{


const result = a+b; // 1-e выражение
const result2 = result*2; // 2-e выражение
return result2; // 3-e выражение
}

//ее я не смогу укоротить. Будет ошибка


const sumFE = (a,b) => const result = a+b; const result2 = result*2; return result2; // не надо так!

Возврат из функции
return - вот что поможет вернуть результат функции.
Надо запомнить, что функция без return ничего не возвращает, то есть undefined.
Сравни

function sum1(a,b){
const result = a+b;
return result;
}

function sum2(a,b){
const result = a+b;
}

console.log(sum1(2,3));// 5, потому что есть return


console.log(sum2(2,3));// undefined потому что НЕТ return

Возврат стрелочной функции.


Return в стрелочной функции можно писать, а можно не писать.

1.5. Функции 5
const sum1 = (a,b) =>{
return a+b;
}
const sum2 = (a,b) =>{
a+b;
}
const sum3 = (a,b) => a+b;
const sum4 = (a,b) => {a+b};

console.log(sum1(2,3));// 5
console.log(sum2(2,3));// undefined
console.log(sum3(2,3));// 5
console.log(sum4(2,3));// undefined

Значение по умолчанию для параметров


Значение по умолчанию срабатывает в том случае, когда мы не передали аргумент при
вызове. Если значение по умолчанию задано и при вызове передан аргумент, то приоритет
у аргумента.

function login(email, password = 123123){


console.log(email);
console.log(password);
}

1) login("[email protected]", "verystrongpassword");
2) login("[email protected]");
3) login();

1 - выведет "[email protected]" и "verystrongpassword"


2 - выведет "[email protected]" и 123123
3 - выведет undefined и 123123

Про переменные с функциями


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

let externalVariable = 10;

1.5. Функции 6
function showVariable() {
let internalVariable = 5;
console.log(externalVariable);
console.log(internalVariable);
}

showVariable(); // 10, 5
console.log(internalVariable);// ReferenceError: internalVariable is not defined

Тут переменная internalVariable за функцией “не видна”, поэтому будет ошибка.


Тема функции такая тема, которая дальше будет встречаться в КАЖДОЙ главе. Это
самая важная тема. Ее будешь применять на работе каждый день.
Выполни задания и закрепи эту тему.

Задания
1. Напиши функцию, которая определяет, является ли число положительным,
отрицательным или равным нулю.

2. Напиши функцию, которая проверяет, является ли число четным или нечетным.

3. Напиши функцию, которая выводит большее из двух чисел.

4. Напиши функцию, которая проверяет, попадает ли переданное число в заданный


диапазон.

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

6. Напиши функцию, которая принимает на вход число и выводит в консоль таблицу


умножения для этого числа от 1 до 10.

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

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

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы прислушаемся к ней
и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и остальных студентов!
Заполни форму

https://forms.gle/sGRDJSTkJYNXuXsu7

1.5. Функции 7
🕣
2.1. Числа
Number в JavaScript - это тип данных, который используется для хранения
числовых значений.

Тип данных «число» ( number ) содержит числа (целые и дробные), а также


специальные значения Infinity , -Infinity , NaN (Not a Number).

Числа записываются с использованием цифр, а разделение целой и десятичной


части осуществляется с помощью точки.

const num = 5;
const negativeNumber = -5
const decimal = 0.15 // или .15 (результат одинаковый)

Также можно использовать экспоненциальный формат, чтобы задать большие


либо маленькие числа.

const a = 3e6; //3000000


const b = 2e-3; //0.002

Специальные значения
В JavaScript есть три специальных значения. Эти значения принадлежат
типу number , но не работают как обычные числа:

бесконечность Infinity ;

минус бесконечность -Infinity ;

не число (not a number) NaN .

Infinity мы можем получить при делении положительного числа на 0;


-Infinity - при делении отрицательного числа на 0;
NaN - в результате математической операции с недопустимым операндом;

2.1. Числа 1
Значение NaN “прилипчиво”. Любая операция с NaN возвращает NaN:

console.log(5/0); //Infinity
console.log(-5/0) //-Infinity
console.log("Redev"/4) //NaN

используется для сообщения о том, что результат операции не является


NaN

числом. В JavaScript существует пять операций, которые могут возвратить NaN :

ошибка парсинга числа ( parseInt("Redev") ) ;

математическая операция с недопустимым результатом (корень из

отрицательного) ;

один из операндов в арифметической операции имеет значение NaN . (5+NaN) ;

арифметическая операция с неопределенными операндами (undefined +

undefined) ;

арифметическая операция со строкой, кроме сложения. ("Redev"/4) .

NaN не равен самому себе, поэтому по-простому проверить, что


в переменной хранится NaN, не получится.

Но для этого есть специальный метод Number.isNaN(…) .

const result1 = "Redev"/4;


const result2 = 8*2;

console.log(Number.isNaN(result))// true
console.log(Number.isNaN(result2))// false

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


специальным значением, используйте функцию Number.isFinite() . Она возвращает
true, если переданный аргумент - число.

const a = Infinity
const b = NaN
const c = 100

console.log(Number.isFinite(a)) // false

2.1. Числа 2
console.log(Number.isFinite(b)) // false
console.log(Number.isFinite(c)) // true

parseInt()
Функция parseInt(string, radix) анализирует строку и возвращает целое число
согласно указанной системе счисления. radix - это система счисления. Если не
указать ее, по умолчанию будет десятичная (почти всегда).

А теперь своими словами: parseInt достает из строки число…но с небольшими


подвохами. Глянь примеры ниже:

parseInt(string, radix);

parseInt("123asd"); //123
parseInt("qwe123asd"); //NaN
parseInt("asd123"); //NaN
parseInt("12 3asd"); //12
parseInt(" 123asd"); //123
parseInt("3e6"); //3

То есть:

если строка начинается с числа, parseInt() парсит строку посимвольно до


первого НЕ ЧИСЛА и возвращает что нашел.

если строка начинается с не числа, parseInt() вернет NaN

Пробел в начале игнорируется

с экспонентой parseInt не работает (”3e6” → 3)

Есть еще метод parseFloat , если хочешь, можешь про него почитать тут

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

Вот пример свойств и методов у Math:


Math.PI

2.1. Числа 3
Число ПИ. примерно 3.14159 .
Math.max()

Возвращает наибольшее из чисел.


Math.min()

Возвращает наименьшее из чисел.


Math.pow()

Возвращает основание x степени y (то есть x**y ).


Math.random()

Возвращает псевдослучайное число между 0 и 1 .


Math.round()

Возвращает значение числа, x округленное до ближайшего целого числа.


Math.sqrt()

Возвращает квадратный корень из x .

console.log(Math.PI); //3.141592653589793

const maxNumber = Math.max(3,5,1,83,1,57,3);


console.log(maxNumber); //83

const minNumber = Math.min(3,5,1,83,1,57,3);


console.log(minNumber); //1

const sqrt = Math.sqrt(9);


console.log(sqrt); //3

BigInt
BigInt - это числовые значения, которые слишком большие для представления в
виде примитивного типа number.
Создается с помощью добавления n в конец целочисленного литерала или
вызовом функции BigInt() и присвоением ей целочисленного или строкового
значения.

const a = 123n;
const b = BigInt(123123123123123) // 123123123123123n

console.log(typeof a) // "bigint"

2.1. Числа 4
В Redev мы не уделяем этой теме времени. Если хочешь, можно почитать
документацию

Задания
1. Какой будет результат?

parseInt('17px'); // ?
parseInt('17px10'); // ?
parseInt('pas123'); // ?
parseInt(' 123px'); // ?
parseInt('6e6'); // ?

2. Напиши функцию, которая принимает два числа и возвращает их сумму.

3. Напиши функцию, которая принимает число и возвращает его квадрат.

4. Напиши функцию, которая принимает три числа и возвращает наименьшее из


них.

5. Напиши функцию, которая принимает число и возвращает его факториал


(можно и нужно погуглить).

6. Напиши функцию, которая принимает число и возвращает true, если оно


четное, и false, если нечетное.

7. Напиши функцию, которая сгенерирует рандомное число в диапозоне от 1 до 5


(можно и нужно погуглить).

8. Перепиши предыдущую функцию с возможностью задавать диапозон через


аргументы функции.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/fnTMTnzjBcndvJc16

2.1. Числа 5
🌙
2.2. Строки
Любые текстовые данные в JavaScript — это строки (англ. string)

String тип данных в JavaScript, который представляет собой набор символов,


заключенных в кавычки.

Кавычки
В JavaScript есть разные типы кавычек.

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

const single = 'Redev';


const double = "Redev";
const str = `Паша из Redev`;

Одинарные и двойные кавычки работают одинаково, но если использовать


обратные кавычки, то можно вставлять в строку любые выражения, оборачивая их
в ${...}.

const name = "Паша"


const str = `${name} из Redev`;
console.log(str); // `Паша из Redev`

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

const name = "Паша


Гуцу" // тут ошибка

const name = `Паша


Гуцу`; // тут НЕТ ошибки

2.2. Строки 1
Можно использовать один тип кавычек внутри строки, с объявленой другим типом.
Двойные в одинарных или одинарные в двойных.

const str = 'Я точно стану "программистом"';


console.log(str); // Я точно стану "программистом"

const str = "Я точно стану 'программистом'";


console.log(str); // Я точно стану 'программистом'

Длина строки
Свойство length содержит длину строки. Через него можно узнать количество
символов с строке.

const name = "Паша"


console.log(name.length); //4

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

Доступ к символам
Отдельный символ строки можно получить по порядковому номеру символа в
строке, нумерация которого начинается с 0:

const course = 'Redev';

console.log(course[0]) // "R"
console.log(course[2]) // "d"

Тут мы использовали [position], но так же можно использовать метод


.at(position) .

const course = 'Redev';

2.2. Строки 2
console.log(course.at(0)) // "R"
console.log(course.at(-3)) // "d"

Как можно видеть, преимущество метода .at(position) заключается в том, что он


позволяет использовать отрицательные значения для позиции. Если position -
отрицательное число, то отсчет идет с конца строки. Таким образом, .at(-1)

означает последний символ, а .at(-2) - символ, который идет перед ним и так
далее.
Квадратные скобки всегда возвращают undefined для отрицательных индексов.

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


когда вы делаете изменения в строке, вы создаете новую
строку, а не изменяете существующую.

Методы строк
Все методы ты можешь посмотреть в таблице документации.

А вот про эти методы мы поговорим:

.toUpperCase()

.toLowerCase()

.indexOf() / .includes()

.slice()

.substring()

.trim()

.repeat()

Ниже ты найдешь описание методов и примеры их использования, а если мало


этих методов, то вот документация

.toUpperCase() / .toLowerCase()
Метод .toUpperCase() возвращает копию строки, в которой все символы
преобразованы в верхний регистр, а .toLowerCase() соответственно в нижний;

2.2. Строки 3
const course = 'Redev';

console.log(course.toUpperCase()) // "REDEV"
console.log(course.toLowerCase()) // "redev"

Обращаю внимание, что исходная строка не меняется при


использовании этих методов, вместо этого возвращается новая
строка с измененным регистром.

.indexOf() / .includes()
и .includes() - это методы строк в JavaScript, которые используются для
.indexOf()

поиска подстроки в строке.

.indexOf(searchString) возвращает индекс (позицию) первого вхождения подстроки


searchString в строку. Если подстрока не найдена, метод возвращает -1.

const str = "Hello, Redev!";


console.log(str.indexOf("dev")); // выведет 9
console.log(str.indexOf("development")); // выведет -1

возвращает true, если подстрока


.includes(searchString) searchString входит в
строку, и false в противном случае.

const str = "Hello, Redev!";


console.log(str.includes("dev")); // выведет true
console.log(str.includes("development")); // выведет false

Оба принимают обязательный параметр searchString , который является искомой


подстрокой.
Также оба метода принимают необязательный параметр position (позиция),
который указывает, с какой позиции начинать поиск подстроки в строке. Если
параметр не указан, то поиск начинается с начала строки.

const str = "Hello, Redev!";


console.log(str.includes("Hello", 1)); // выведет false
console.log(str.indexOf("Hello", 1)); // выведет -1

2.2. Строки 4
В приведенном выше примере, position установлен в 1, так что поиск подстроки
"Hello" начинается с позиции 1, и поэтому методы возвращают false или -1 .

.slice()
Он используется для извлечения части строки. Он принимает два аргумента:
начальный индекс и конечный индекс (опциональный).

let string = "Hello, world!";


let slicedString = string.slice(7, 12);
console.log(slicedString); // выведет "world"

В этом примере slice вырезает часть строки, начиная с 7-го индекса и заканчивая
12-м (не включая его). Таким образом, извлекается слово "world".

Если второй аргумент не указан, slice вырезает часть строки от начального


индекса до конца строки. Например:

const string = "Hello, world!";


const slicedString = string.slice(7);
console.log(slicedString); // выведет "world!"

Если начальный индекс отрицателен, slice вычисляет его относительно конца


строки. Например:

const string = "Hello, world!";


const slicedString = string.slice(-6);
console.log(slicedString); // выведет "world!"

Этот метод не изменяет исходную строку, а вместо этого возвращает новую


строку с извлеченной частью.

const course = 'Redev Courses';

console.log(course.slice(1,3)) // "ed"
console.log(course.slice(2,7)) // "dev C"
console.log(course.slice(6)) // "Courses"

2.2. Строки 5
.substring()
Это метод строк в JavaScript, который используется для извлечения подстроки из
строки. Он принимает два аргумента: начальную и конечную позицию для
извлечения подстроки. Начальная позиция включается в извлекаемую подстроку,
а конечная - нет.

const course = 'Redev Courses';

console.log(course.substring(1,3)) // "ed"
console.log(course.substring(3,1)) // "ed" *
console.log(course.substring(2,7)) // "dev C"
console.log(course.substring(6)) // "Courses"

Как мы видим практически тоже самое что и .slice(), но разница есть, и вот какая:

1. Параметры: .slice() принимает два аргумента - начальную и конечную


позицию для извлечения подстроки, а .substring() принимает только две
позиции . То есть можно их поменять местами

2. Отрицательные значения: .slice() может принимать отрицательные


значения для позиций, что означает, что он будет отсчитывать от конца строки.
В то время как .substring() не поддерживает отрицательные значения. Если все
таки передать его, он станет 0.

3. * Порядок аргументов: если первый аргумент больше второго в .substring() ,


то он автоматически меняет их местами, а .slice() не делает этого.

.trim()
Метод убирает лишние пробелы с начала и с конца строки.

const course = ' Redev ';


const exmpl = ' Redev Courses ';
console.log(course.trim())) // "Redev"
console.log(exmpl.trim())) // "Redev Courses"

Удаляет только пробелы с начала и конца строки, а не из всей строки.


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

2.2. Строки 6
пробелов в начале или конце строки, введенных пользователем.

.repeat()
.repeat() - это метод строк в JavaScript, который возвращает новую строку,
состоящую из повторения исходной строки заданное количество раз. Например:

const course = 'Redev';


console.log(course.repeat(2)); // "RedevRedev"

Параметр repeat - это целое число, указывающее количество повторений строки.


Если значение меньше или равно 0, возвращается пустая строка. Если значение
не является целым числом, то количество будет преобразовано в целое число. т.е.
если мы пишем число 2.9, то оно будет преобразовано в 2, а не в ближайшее 3.

Сравнение строк
Строки в JavaScript сравниваются по их Unicode-кодам. Это означает, что строки
сравниваются посимвольно, начиная с первых символов. Если символы равны,
то сравниваются следующие символы, и так далее, пока не будет найдено отличие
или до конца строк.

Можно сравнить строки используя стандартные операторы сравнения.

console.log("apple" == "banana"); // выведет false


console.log("apple" < "banana"); // выведет true

Давайте разбираться почему "apple" < "banana" будет true?


Это потому что оператор < производит сравнение строк по их порядку в Unicode.
Если сравниваемые строки являются разными, то система сравнения выбирает
строку, которая идет раньше в таблице Unicode. Грубо говоря у каждого символа
есть свой порядковый номер и по этому номеру и сравнивается.
”a” - 61

”b” - 62
”c” - 63
…..
и так каждый символ.

2.2. Строки 7
Вот тут можно посмотреть коды для алфавита https://unicode-table.com/ru/

Соотвественно “а” < “b” (тоже самое что и 61 < 62) - и это true

Задачи
1. Напиши функцию, которая ищет индекс первого вхождения заданной
подстроки в строку и возвращает его.

2. Напиши функцию, которая возвращает длину строки без учета пробелов.

3. Напиши функцию, которая возвращает повторенную строку некоторое


количество раз.

4. Напиши функцию, которая принимает две строки в качестве аргументов и


возвращает true, если первая строка является подстрокой второй строки, и
false в противном случае.

5. Напиши функцию, которая принимает строку в качестве аргумента и


возвращает количество чисел, которые содержатся в этой строке.

6. Напиши функцию, которая принимает число в качестве аргумента и


возвращает это число в обратном порядке. Например, если передано число
123, функция должна вернуть число 321.

7. Напиши функцию, которая принимает строку в качестве аргумента и


возвращает количество слов в этой строке.

8. Напиши функцию, которая принимает три строки в качестве аргументов:


первая строка - исходная строка, вторая строка - строка для поиска, третья
строка - строка для замены. Функция должна вернуть исходную строку с
замененной подстрокой.

9. Напиши функцию, которая принимает строку в качестве аргумента и


возвращает эту же строку, но со всеми буквами в верхнем регистре.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и

2.2. Строки 8
остальных студентов!
Заполни форму

https://forms.gle/LQGhforDLrE5FDxB8

🚥 2.3. Объекты. Основы

2.2. Строки 9
🚥
2.3. Объекты. Основы
Объект - это структура данных, которая позволяет хранить множество свойств.
Свойство - это пара "ключ-значение". Ключи могут быть строками или
символами, а значения могут быть любым типом данных, включая другие
объекты.

Все что нас окружает это объект.

В JavaScript есть несколько способов создать объект:

2.3. Объекты. Основы 1


1. Литерал объекта: Один из самых простых способов создать объект - это
использовать литерал объекта, который представляет собой фигурные скобки
{} .

const obj = {};

2. Конструктор Object: Можно также создать объект, используя конструктор


Object .

const obj = new Object();

Пример:

const person = {
fullName: "Pavel Hutsu",
age: 25,
address: {
street: "Bratskaya",
city: "Minsk",
},
};

В объекте person находятся три свойства:

1. Первое свойство с именем "fullName" и значением "Pavel Hutsu" .

2. Второе свойство с именем "age" и значением 25 .

3. Третье свойство с именем “address” и значением еще один объект


{
street: "Bratskaya",
city: "Minsk",
}

Доступ к свойствам
В JavaScript есть несколько способов получить доступ к свойствам объекта:

2.3. Объекты. Основы 2


1. Точечный синтаксис: Один из самых простых способов получить доступ к
свойству объекта - это использовать точечный синтаксис.

const person = {fullName: "Pavel Hutsu", age: 25};


console.log(person.fullName); // Pavel Hutsu

2. Синтаксис квадратных скобок: Можно также использовать синтаксис


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

const person = {fullName: "Pavel Hutsu", age: 25};


const property = "fullName";
console.log(person[property]); // Pavel Hutsu
console.log(person["fullName"]); // Pavel Hutsu

2.3. Объекты. Основы 3


Точно так же мы можем и изменять свойства. Через точку . либо [] . Получить
доступ и присвоить новое значение. Вот примеры:

const person = {fullName: "Pavel Hutsu", age: 25};

person.age = 26;
console.log(person.age); //26

person["age"] = 27;
console.log(person.age); //27

Удаление свойства
delete - это оператор, который удаляет свойство в объекте.
Например, есть объект person:

const person = {fullName: "Pavel Hutsu", hands: true};

Мы можем удалить свойство hands следующим образом:

delete person.hands;
console.log(person); // {fullName: "Pavel Hutsu"

deleteиспользуется, когда необходимо удалить свойство объекта, которое больше


не нужно. Это помогает уменьшить размер объекта и улучшить его
производительность.

2.3. Объекты. Основы 4


Перебор объекта for...in
Цикл for...in используется для перебора свойств объекта. Он позволяет
перебрать все перечисляемые свойства объекта и выполнить некоторые действия
с каждым свойством.

Синтаксис цикла for...in выглядит следующим образом:

for (const key in object) {


// тело
}

где key- имя переменной, которая будет принимать значения ключей объекта, а
object - объект, который нужно перебрать.

Пример использования цикла for...in :

2.3. Объекты. Основы 5


const person = {
firstName: 'Pavel',
lastName: 'Hutsu',
age: 25,
city: 'Minsk'
};

for (const key in person) {


console.table(`${key}: ${person[key]}`);
}

В результате выполнения этого кода будут выведены все свойства объекта person

и их значения.

Хранение объекта

2.3. Объекты. Основы 6


Объект в JavaScript хранится по ссылке. Когда мы создаем объект, мы создаем
ссылку на него, которая указывает на место в памяти, где хранится объект. Когда
мы присваиваем объект другой переменной, мы копируем только ссылку, а не
сам объект. Если мы изменим этот объект через одну из переменных, то
изменения будут видны и через другую переменную.

const person = {fullName: "Pavel Hutsu", age: 25};


const user = person;

user.fullName = "Danil Hutsu";


console.log(person === user); // true
console.log(person.fullName); // Danil Hutsu
console.log(user.fullName); // Danil Hutsu

Надо принять и понять, что в примере выше у нас один объект и 2 переменных,
через которые мы можем “достучаться” к объекту! То есть как мы видим, изменяя
свойство одной переменной, во второй оно тоже изменится. ПОТОМУ ЧТО ОДИН
ОБЪЕКТ!

2.3. Объекты. Основы 7


Сравнение объектов
Объекты в JavaScript сравниваются через их ссылки. Если две ссылки указывают
на один и тот же объект, то они считаются равными. Если же у двух объектов
разные ссылки, то они считаются разными, даже если их свойства идентичны.

const person1 = {fullName: "Pavel Hutsu", age: 25};


const person2 = {fullName: "Pavel Hutsu", age: 25};

console.log(person1 == person2); // false


console.log(person1 === person2); // false

Внешне 2 одинаковых объекта, но ссылки у них разные. Соответственно всегда


будет false!
Даже если сравнивать вот так пустые объекты {}=={} все равно false!

2.3. Объекты. Основы 8


Const с объектами
Когда мы объявляем переменную с помощью const и присваиваем ей объект, мы
не можем переопределить эту переменную новым значением, но мы можем
изменять свойства объекта.
Например:

const user = { name: 'Pavel', age: 25 };


user = { name: 'Alex', age: 28 }; // TypeError: Assignment to constant variable.
user.age = 26; // это допустимо

Важно понимать, что использование const не защищает сам объект от изменения,


а только защищает переменную, которая указывает на объект, от
переопределения.

2.3. Объекты. Основы 9


Клонирование объектов
Есть несколько способов клонировать объект в JavaScript:

1. Через метод Object.assign():

const original = { name: 'Pavel', age: 25 };


const clone = Object.assign({}, original);

console.log(original); // { name: 'Pavel', age: 25 }


console.log(clone); // { name: 'Pavel', age: 25 }
console.log(original === clone); // false

2. Через spread оператор:

const original = { name: 'Pavel', age: 25 };


const clone = { ...original };

2.3. Объекты. Основы 10


console.log(original); // { name: 'Pavel', age: 25 }
console.log(clone); // { name: 'Pavel', age: 25 }
console.log(original === clone); // false

3. Через JSON.parse/JSON.stringify:

const original = { name: 'Pavel', age: 25 };;


const clone = JSON.parse(JSON.stringify(original));

console.log(original); // { name: 'Pavel', age: 25 }


console.log(clone); // { name: 'Pavel', age: 25 }
console.log(original === clone); // false

Предпочтительней использовать второй способ!

4. structuredClone()

Отдельно хочу поговорить про новый способ, глубокого клонирования


structuredClone

Этот метод позволяет создавать глубокую копию объекта с сохранением его


структуры, включая все вложенные объекты и массивы.

Представь, что у тебя есть объект person с несколькими свойствами:

const person = {
name: "Pavel",
age: 25,
address: {
street: "Bratskaya",
city: "Minsk",
zip: "222842"
},
hobbies: ["coding", "coding", "coding"]
};

Если ты хочешь создать копию этого объекта, чтобы изменения в копии не влияли
на оригинальный объект, ты можешь использовать spread оператор (…):

const copy = {...person};

copy.address.street = "Makarevicha";

2.3. Объекты. Основы 11


console.log(copy.address.street); // "Makarevicha"
console.log(person.address.street); // "Makarevicha"

Однако, если у person есть вложенные объекты или массивы, они будут
скопированы только по ссылке, а не по значению. Это значит, что если ты
изменишь свойство street в объекте address , это изменение отразится как в
оригинальном объекте, так и в копии.
Чтобы создать глубокую копию объекта, ты можешь использовать метод
structuredClone . Этот метод доступен во всех современных браузерах и может

использоваться как для простых объектов, так и для объектов с вложенными


объектами и массивами.

const copy = structuredClone(person);

copy.address.street = "Makarevicha";

console.log(copy.address.street); // "Makarevicha"
console.log(person.address.street); // "Bratskaya"

То есть, при изменении свойства внутреннего объекта у clone , свойство у


изначального объекта person не меняется.

Синтаксис structuredClone

structuredClone(value)
structuredClone(value, options)

Метод имеет два параметра: value и options .

value- это объект, который мы хотим скопировать. Он может быть любого типа,
включая объекты, массивы, примитивы, Map, Set и…

options- необязательный параметр, который позволяет настроить поведение


метода. Этот параметр имеет два свойства: transfer и signal .

Возвращает глубокую копию объекта.

2.3. Объекты. Основы 12


более подробно можно ознакомиться в документации
https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

Класс Object
Object - это встроенный класс в JavaScript, который предоставляет методы для
работы с объектами. Он является родительским классом для всех объектов в
JavaScript.

Некоторые из методов, которые предоставляет класс Object :

Object.assign() - копирует свойства из одного или нескольких объектов в другой


объект.

const person = { name: 'Pavel' };


const age = { age: 25 };

Object.assign(person, age);
console.log(person); // { name: 'Pavel', age: 25 }

В этом примере мы копируем свойства из объекта age в объект person . Теперь


объект person содержит два свойства: name и age .

- создает новый объект с указанным прототипом. Про него


Object.create()

подробнее поговорим в теме прототипы.

Object.freeze() - замораживает объект, предотвращая добавление, удаление


или изменение его свойств.

const person = {
name: 'Pavel',
age: 25
};

Object.freeze(person);
person.name = 'Alesha'; // не будет работать, т.к. объект заморожен

console.log(person.name); // Pavel

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

2.3. Объекты. Основы 13


const person = {
name: 'Pavel',
age: 25,
};

const keys = Object.keys(person);


console.log(keys); //[ 'name', 'age' ]

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

const person = {
name: 'Pavel',
age: 25,
};

const values = Object.values(person);


console.log(values); //[ 'Pavel', 25 ]

- возвращает массив с парами ключ-значение для каждого


Object.entries()

свойства объекта.

const person = {
name: 'Pavel',
age: 25,
};

const entries = Object.entries(person);


console.log(entries); // [ [ 'name', 'Pavel' ], [ 'age', 25 ]]

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

2.3. Объекты. Основы 14


Есть два способа создания метода объекта:

1. Создание метода при объявлении объекта:

const person = {
name: 'Pavel',
age: 25,
sayHi: function() {
console.log(`Hello`);
},
run: function() {
console.log(`I'm running`);
}
};

person.sayHi(); // `Hello`

2. Создание метода после объявления объекта:

2.3. Объекты. Основы 15


const person = {
name: 'Pavel',
age: 25
};

person.sayHi = function() {
console.log(`привет!`);
};

person.sayHi(); // `привет!`

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

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

2 правила для работы с конструкторами:

Обычно имя конструктора начинается с большой буквы, чтобы указать, что он


является конструктором.

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


ключевое слово "this" . После определения свойств и методов, конструктор
возвращает объект, созданный с помощью ключевого слова "new" .

function Person(name, age) {


this.name = name;
this.age = age;
this.sayHello = function() {
console.log("Hello, my name is " + this.name);
};
}

const person1 = new Person("Pavel", 25);


const person2 = new Person("Nastassia", 27);

console.log(person1.name); // "Pavel"
person2.sayHello(); // "Hello, my name is Nastassia"

2.3. Объекты. Основы 16


В этом примере определен конструктор объектов Person, который принимает два
аргумента - имя и возраст. Внутри конструктора определены свойства name и age,
а также метод sayHello. Затем с помощью ключевого слова "new" создаются два
объекта - person1 и person2. Свойства объектов задаются значениями,
переданными при создании объекта. Метод sayHello вызывается на объекте
person2.

Разница обычной функции и функции конструктора

function user() {} // обычная функция


function User() {} // функция конструктор (потому что принято называть с большой буквы)

const user1 = user();


const user2 = new User();

console.log(user1); // undefined
console.log(user2); // {}

Задачи
1. Напиши функцию, которая принимает объект и возвращает массив его ключей.

2. Напиши функцию, которая сливает два объекта вместе и возвращает новый


объект со всеми свойствами из обоих объектов.

3. Напиши функцию, которая принимает объект и возвращает сумму всех его


значений (числа).

4. Напиши функцию, которая считает количество свойств в объекте и возвращает


это число.

5. Напиши функцию, которая принимает два объекта и сравнивает их свойства.


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

6. Напиши функцию, которая принимает объект и возвращает массив его


значений.

7. Напиши функцию, которая принимает объект и удаляет определенное


свойство из него (ключ свойства передать в параметрах)

2.3. Объекты. Основы 17


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

9. Напиши функцию, которая принимает объект и выводит все свойства в виде


строки "key: value"

10. Напиши функцию, которая принимает объект и выводит имена методов.

11. Создай объект car с методами start и stop , которые выводят в консоль
сообщения "Starting the car" и "Stopping the car" соответственно. Добавь
свойство isRunning , которое будет устанавливаться в true при вызове метода
start ив false при вызове метода stop .

12. Создай объект book с методами open и close , которые выводят в консоль
сообщения "Opening the book" и "Closing the book" соответственно. Добавь
свойство currentPage , которое будет хранить текущую страницу, на которой
находится пользователь. Добавь метод turnPage , который увеличивает
currentPage на 1 и выводит в консоль сообщение "Turning page {page}", где

{page} - номер текущей страницы. Используй this для доступа к свойству


currentPage внутри метода turnPage .

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/U3g2euddqvL8FugLA

🤯 2.4 Объекты. Углубиться

2.3. Объекты. Основы 18


🤯
2.4 Объекты. Углубиться
!!! Глубокое и поверхностное
копирование !!!
Глубокое копирование (deep copy) объекта означает, что мы создаем полную
копию исходного объекта, включая все его свойства и внутренние объекты или
массивы. Если исходный объект меняется, то эти изменения не влияют на клон.

Например, есть объект person :

const person = {
fullName: "Pavel Hutsu",
age: 25,
address: {
street: "Bratskaya",
city: "Minsk",
},
};

Если мы сделаем глубокое клонирование этого объекта, то получим полную копию


person , которая будет иметь те же свойства и внутренние объекты.

const personClone = JSON.parse(JSON.stringify(person));

Теперь, если мы изменим исходный объект person , например, изменив его возраст,
то это изменение не влияет на клон:

person.age = 40;
console.log(personClone.age); // 30

Поверхностное копирование (shallow copy) - это копирование только его


свойств и значений, без копирования внутренних объектов или массивов. Таким

2.4 Объекты. Углубиться 1


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

Например, есть тот же объект person :

const person = {
fullName: "Pavel Hutsu",
age: 25,
address: {
street: "Bratskaya",
city: "Minsk",
},
};

Если мы сделаем поверхностное клонирование этого объекта, то получим новый


объект с теми же свойствами и значениями, но ссылающимся на тот же
внутренний объект address :

const personClone = {...person};

Теперь, если мы изменим исходный объект person , например, изменив его


внутренний объект address , то это изменение влияет и на клон:

person.address.city = 'Brest';
console.log(personClone.address.city); // Brest
console.log(person.address.city); // Brest

2.4 Объекты. Углубиться 2


!!! this !!!
this - это ключевое слово в JavaScript, которое указывает на текущий объект. Это
значение может меняться в зависимости от контекста, в котором вызывается
код.
В объекте, this указывает на текущий объект, в котором вызывается метод. Тебе
нужно запомнить фраз “this это объект перед точкой в момент вызова метода”
Например:

const person = {
name: 'Pavel',
age: 25,
sayHi: function() {
console.log(`Привет, меня зовут ${this.name}`);
}
};

person.sayHi(); // `Привет, меня зовут Pavel`

В этом примере, this указывает на объект person , и при вызове метода sayHi мы
можем достучаться до его свойства name с помощью this.name .

2.4 Объекты. Углубиться 3


Также надо отметить, что this может использоваться вне
объектов, но в этом случае оно будет указывать на глобальный
объект, в браузере это window , а в Node.js это global .

function greet() {
console.log(this); // global
console.log(`Hello, my name is ${this.name}`);
}

greet(); // Hello, my name is undefined

Ниже, для наглядности, я напишу первый пример разными способами.


Где объявить метод не имеет значения!

const person = {
name: 'Pavel',
age: 25,
};
person.sayHi = function () {
console.log(`Привет, меня зовут ${this.name}`);
}
person.sayHi(); // `Привет, меня зовут Pavel`

const person = {
name: 'Pavel',
age: 25,
};

function sayHi() {
console.log(`Привет, меня зовут ${this.name}`);
}

person.sayHi = sayHi;

person.sayHi(); // `Привет, меня зовут Pavel`

const person = {
name: 'Pavel',

2.4 Объекты. Углубиться 4


age: 25,
};

const sayHi = function () {


console.log(`Привет, меня зовут ${this.name}`);
}

person.sayHi = sayHi;

person.sayHi(); // `Привет, меня зовут Pavel`

Видишь, разницы нет. Просто ты теперь знаешь, что можно и так и так

this и стрелочная функция


Давай рассмотрим такой пример:

const obj = {
myProperty: 42,
myMethod: () => {
console.log(this.myProperty);
}
}

obj.myMethod(); // undefined

Выводит “undefined” давай разберемся почему.

Когда мы используем обычную функцию в JavaScript, значение this зависит от


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

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

Давай смотреть пример:

const obj = {
myProperty: 42,
myMethod: () => this.myProperty,
myMethod2: function () {

2.4 Объекты. Углубиться 5


const fn = () => this.myProperty;
return fn()
}
}

console.log(obj.myMethod()); // undefined
console.log(obj.myMethod2()); // 42

Функция fn была объявлена внутри функции myMethod2 соответсвенно ее this


берется из контекста объявления и будет равен this myMethod2

Еще можно запомнить это как “this в стрелочной функции берется извне. Там где
она объявлена, а не вызывается! ”
В коде ниже это сразу видно:

const fn3 = () => this.myProperty;

const obj = {
myProperty: 42,
myMethod: () => this.myProperty,
myMethod2: function () {
const fn = () => this.myProperty;
return fn()
},
myMethod3: function () {
return fn3()
}
}

console.log(obj.myMethod()); // undefined
console.log(obj.myMethod2()); // 42
console.log(obj.myMethod3()); // undefined

Разбери пример выше! Он поможет понять как работает this со стрелочной


функцией.

call, bind и apply


call , bind и apply являются методами, доступными для всех функций в
JavaScript. Они используются для управления значением this внутри функций.
На стрелочную функцию call, bind и apply не влияют!

2.4 Объекты. Углубиться 6


Метод call вызывает функцию и устанавливает значение this для этой функции
в первый аргумент, переданный методу call . Последующие аргументы
передаются как аргументы вызываемой функции:

function greet(greeting) {
console.log(`${greeting}, my name is ${this.name}`);
}

const person = {
name: 'Pavel'
};

greet('Hello'); // Hello, my name is undefined


greet.call(person, 'Hello'); // Hello, my name is Pavel

Метод apply аналогичен методу call , за исключением того, что аргументы


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

function greet(greeting) {
console.log(`${greeting}, my name is ${this.name}`);
}

const person = {
name: 'Pavel'
};

greet.apply(person, ['Hello']); // Hello, my name is Pavel

Метод bind также устанавливает значение this для функции, но возвращает


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

function greet() {
console.log(`Hello, my name is ${this.name}`);
}

const person = {
name: 'Pavel'
};

let greetPerson = greet.bind(person);


greetPerson(); // Hello, my name is Pavel

2.4 Объекты. Углубиться 7


В общем, методы call , bind и apply позволяют управлять значением this в
функциях и сделать их более гибкими и переиспользуемыми.

Задачи
1. Создай объект person с свойством name и методом greet , который выводит в
консоль строку "Hello, my name is {name}". Используй this внутри метода
greet для получения значения свойства name объекта person .

2. Создай функцию calculate с тремя аргументами: a , b и функцией operation .


Функция operation должна выполнять определенную операцию (например,
сложение, вычитание, умножение или деление) с a и b . Используй методы
call , apply и bind , чтобы вызвать функцию operation и установить значение

this в объект calculator , имеющий свойства add , subtract , multiply и divide ,

которые представляют операции сложения, вычитания, умножения и деления


соответственно.

3. Создай объект button со свойством text и методом click , который выводит в


консоль значение свойства text . Используй метод bind , чтобы создать новую
функцию boundClick , которая связывает значение this с объектом button .
Затем вызовите boundClick в качестве обработчика события для клика на
кнопке.

4. Создай объект game с методом play , который выводит в консоль "Playing {title}
game". Используй метод call или apply , чтобы вызвать метод play с
объектами basketballGame и chessGame , имеющими свойства title , которые
представляют соответствующие игры.

5. Создай объект dog с методом bark , который выводит в консоль "Woof!".


Создайте объект cat с методом meow , который выводит в консоль "Meow!".
Используй метод call или apply , чтобы вызвать методы bark и meow с
объектом dog и cat соответственно, чтобы вывести в консоль
соответствующие звуки.

6. Создай объект calculator с методами add , subtract , multiply и divide , которые


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

2.4 Объекты. Углубиться 8


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

7. Создай объект player с методом play , который выводит в консоль сообщение


"Playing {game}", где {game} - название игры. Добавь свойство games , которое
будет содержать список игр, в которые игрок может играть. Используй цикл
for...of , чтобы перебрать список игр и вызвать метод play для каждой игры.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/k2uKurkpeJgUXhub8

🛎 3.1. Массивы

2.4 Объекты. Углубиться 9


🛎
3.1. Массивы
Массив - это объект, который содержит упорядоченный набор элементов.
Каждый элемент может быть любого типа данных, включая другие массивы.
Доступ к элементам массива осуществляется через индекс, который начинается с
нуля!

Массив имеет тип данных object. typeof [1,2,3]; // “object” соотвественно и


сравниваются массивы по таким же правилам как и объекты (по ссылке).

Создание массива
3.1. Массивы 1
Есть несколько способов создать массив. Легче всего создать массив используя
квадратные скобки и разделяя элементы запятой. Элементы массива могут быть
любым выражением, в том числе объектами.

const empty = []; // Пустой массив


const numbers = [2, 3, 5, 7, 11]; // Массив с пятью числовыми элементами
const mix = [ 1.1, true, "a", ]; // 3 элемента разных типов + завершающая запятая
const base = 1024; // Объявляем переменную
const arrayBase = [base, base+1, base+2, base+3]; // Массив с переменными
const arrObj = [[1,{x:1, y:2}], [2, {x:3, y:4}]]; // 2 массива внутри, содержащие объекты

Еще варианты создания массива:


1. Вызвать конструктор без аргументов:

const arr = new Array();

В этом случае будет создан пустой массив, эквивалентный литералу [].

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


длину массива:

const arr = new Array(10);

Использование Array() с одним числом, указывает длину массива. Это может


быть полезно если мы знаем сколько элементов массив будет содержать
заранее. Однако в этом случае, массив будет содержать 10 пустых элементов,
при обращении к которым в них будет находиться undefined.

3. Явно указать в вызове конструктора значения первых двух или более элементов
массива или один нечисловой элемент:

const arr = new Array(5, 4, 3, 2, 1, "тест");

Этот способ менее удобен чем использовать литерал массива.


Но массив он создаст аналогичный записи:
const arr = [5, 4, 3, 2, 1, "тест"]

3.1. Массивы 2
Про длину (.length)
Длина массива - это количество элементов в массиве*. Для получения длины
массива в используется свойство .length , которое является числовым значением,
равным количеству элементов в массиве.

Например, чтобы узнать длину массива arr , можно использовать следующий код:

const arr = [1, 2, 3, 4, 5];


console.log(arr.length); // выводит 5

В данном примере свойство length возвращает значение 5 , так как массив


содержит 5 элементов.

Важно отметить, что свойство length динамически изменяется при добавлении


или удалении элементов из массива. Например, если мы добавим новый элемент
в массив, то его длина увеличится на 1:

const arr = [1, 2, 3, 4, 5];


arr.push(6); // добавляем элемент в конец массива
console.log(arr.length); // выводит 6

Аналогично, если мы удалим элемент из массива, его длина уменьшится:

const arr = [1, 2, 3, 4, 5];


arr.pop(); // удаляем последний элемент массива
console.log(arr.length); // выводит 4

В определении длины массива стоит звездочка, к этому вопросу мы еще вернемся


дальше…потому что .length это не совсем про количество элементов и дальше ты
поймешь почему.

Доступ, изменение и удаление элементов


массива
Доступ к элементам массива осуществляется через индекс элемента. Индексы
начинаются с нуля, то есть первый элемент имеет индекс 0, второй элемент -

3.1. Массивы 3
индекс 1 и т.д.

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

const myArray = ['яблоко', 'апельсин', 'груша'];


console.log(myArray[0]); // выведет 'яблоко'
console.log(myArray[1]); // выведет 'апельсин'
console.log(myArray[2]); // выведет 'груша'

Также можно изменять значение элементов массива, присваивая новые значения


по индексу:

myArray[0] = 'банан';
console.log(myArray); // выведет ['банан', 'апельсин', 'груша']

Вроде не сложно, указываешь индекс и присваиваешь новое значение.

А что будет если я укажу индекс, которого пока нет в массиве?

const myArray = ['яблоко'];


console.log(myArray); // ['яблоко']

myArray[3] = 'банан'; // элементу с индексом 3 присваиваю новое значение

console.log(myArray); // [ 'яблоко', <2 empty items>, 'банан' ]

Так как массив это УПОРЯДОЧЕННАЯ КОЛЛЕКЦИЯ то и результат будет


содержать пустые слоты для хранения элементов. Когда мы выводим массив в
консоль, эти пустые слоты отображаются как <2 empty item> .
Какая же в таком случае будет длина?

console.log(myArray.length); // 4

Как мы видим длина станет 4. Почему так? Ведь выше говорили, что .length - это
количество элементов в массиве. Да, это так, но давай чуть-чуть уточним. На
самом же деле .length это СТАРШИЙ ИНДЕКС +1.

3.1. Массивы 4
Сейчас поясню.
Какой СТАРШИЙ индекс есть у myArray? Конечно же 3. Мы его сами задали и
присвоили элементу - банан . Соответственно старший индекс + 1 это 3 + 1 = 4;

Вот теперь ты знаешь, что такое на самом деле свойство .length .

Его кстати еще можно изменять. Смотри:

const myArray = [3,5,2,6];


console.log(myArray, myArray.length); // [3,5,2,6], 4

myArray.length = 2;
console.log(myArray, myArray.length); // [3,5], 2

То есть изменяя длину массива мы можем влиять на его количество элементов.


Отсюда вытекает самый быстрый способ очистить массив. Просто занулить его
длину:

const myArray = [3,5,2,6];


myArray.length = 0;

console.log(myArray, myArray.length); // [], 0

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

const arr = [1, 2, 3, 4, 5];


console.log(arr.length); // 5
delete arr[2]; // удаляем элемент с индексом 2 (третий элемент массива)
console.log(arr); // [1, 2, undefined, 4, 5]
console.log(arr.length); // 5

То есть, вроде бы удалил, но длина массива при этом не изменилась и появился


пустой элемент. Такое нам не надо.
Для НОРМАЛЬНОГО удаления элемента из массива есть метод .splice() , но про
него поговорим после, в методах массива.

3.1. Массивы 5
Перебор массива
1. Перебор массива с помощью цикла for. Для этого используется следующий
синтаксис:

const arr = [1, 2, 3, 4, 5];

for (let i = 0; i < arr.length; i++) {


console.log(arr[i]);
}

В данном примере мы объявляем массив arr и затем проходимся по каждому


элементу массива, начиная с первого (с индексом 0) и заканчивая последним (с
индексом arr.length - 1). Для этого мы создаем переменную i (i - потому что
сокращенно index), которая принимает значения от 0 до arr.length - 1
(включительно) и используем ее для доступа к каждому элементу массива.

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

const arr = [1, 2, 3, 4, 5];

for (let i = 0; i < arr.length; i++) {


arr[i] = arr[i] + 1;
}

console.log(arr); // [2, 3, 4, 5, 6]

Здесь мы проходимся по каждому элементу массива и увеличиваем его на 1,


затем выводим измененный массив в консоль. Обрати внимание, что мы
изменяем элементы массива непосредственно в цикле for, используя выражение
arr[i] = arr[i] + 1 .

2. Цикл for...of является новым в JavaScript и используется для перебора


элементов массива. С его помощью можно перебирать элементы массива без
необходимости использовать индексы.

Синтаксис цикла for...of выглядит следующим образом:

3.1. Массивы 6
for (const value of array) {
// блок кода
}

В данном примере переменная value содержит текущее значение элемента


массива, который перебирается в цикле. Переменная array - это массив.
Пример использования цикла for...of:

const arr = [1, 2, 3, 4, 5];


let sum = 0;

for (const num of arr) {


sum += num;
}

console.log(sum); // 15

В данном примере мы создали массив arr с пятью элементами и используем цикл


for...of для перебора всех элементов. Затем мы складываем все элементы

массива и выводим сумму в консоль.

Array.isArray()
Метод Array.isArray() используется для проверки, является ли переданный
аргумент массивом или нет. Он возвращает булево значение - true , если аргумент
является массивом, и false , если нет.

Синтаксис метода Array.isArray() :

Array.isArray(value)

где value - это аргумент, который необходимо проверить , а массив ли это.

Пример использования метода Array.isArray() :

const arr = [1, 2, 3];


console.log(Array.isArray(arr)); // true

3.1. Массивы 7
const obj = {name:"Pavel"};
console.log(Array.isArray(obj)); // false

const str = 'Hello Redev';


console.log(Array.isArray(str)); // false

Метод Array.isArray() особенно полезен, если вам необходимо убедиться, что


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

Задания
1. Напиши функцию, которая принимает массив и возвращает сумму четных
элементов в массиве чисел.

2. Напиши функцию, которая принимает массив и возвращает среднее значение


элементов в массиве чисел.

3. Напиши функцию, которая принимает массив и элемент, а возвращает индекс


заданного элемента в массиве.

4. Напиши функцию, которая принимает массив строк и возвращает самую


короткую строку в массиве.

5. Напиши функцию, которая принимает массив и возвращает новый массив


перевернув его задом наперед.

6. Напиши функцию, которая принимает массив чисел и возвращает новый


массив из элементов больше 18.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/TWcTStGQXfpc78RZ9

🏕 3.2. Методы массивов

3.1. Массивы 8
🏕
3.2. Методы массивов
Список всех
Наивысший приоритет
1. forEach() - выполняет указанную функцию один раз для каждого элемента
массива.

2. map()- создает новый массив, содержащий результат вызова указанной


функции для каждого элемента массива.

3. filter()- создает новый массив, содержащий все элементы исходного


массива, для которых указанная функция возвращает true.

4. find() - возвращает первый элемент в массиве, удовлетворяющий условию,


заданному в указанной функции, или undefined, если такой элемент не найден.

5. sort() - сортирует элементы массива.

6. reduce()- применяет указанную функцию к элементам массива слева направо


и возвращает единственное значение.

7. indexOf()- возвращает индекс первого вхождения указанного элемента в


массиве, или -1, если элемент не найден.

8. - возвращает true, если массив содержит указанный элемент, иначе


includes()

возвращает false.

9. splice() - удаляет элементы из массива и возвращает удаленные элементы.

10. join() - объединяет все элементы массива в строку.

11. reverse() - переворачивает порядок элементов массива.

12. fill() - заполняет все элементы массива заданным значением.

Низкий приоритет

3.2. Методы массивов 1


1. push()- добавляет один или несколько элементов в конец массива и
возвращает новую длину массива.

2. pop() - удаляет последний элемент массива и возвращает его значение.

3. shift() - удаляет первый элемент массива и возвращает его значение.

4. - добавляет один или несколько элементов в начало массива и


unshift()

возвращает новую длину массива.

5. flat() - создает новый массив путем выравнивания всех подмассивов в


исходном массиве в один уровень глубины.

6. - возвращает индекс первого элемента в массиве,


findIndex()

удовлетворяющего условию, заданному в указанной функции, или -1, если


такой элемент не найден.

7. every()- возвращает true, если все элементы массива удовлетворяют


условию, заданному в указанной функции.

8. some()- возвращает true, если хотя бы один элемент массива удовлетворяет


условию, заданному в указанной функции.

9. concat() - объединяет два или более массивов и возвращает новый массив.

10. slice()- возвращает новый массив, содержащий выбранные элементы из


исходного массива.

Дальше поговорим про каждый отдельно.

forEach()
Метод массива forEach() выполняет заданную функцию один раз для каждого
элемента массива без необходимости явного использования цикла for или while .

Синтаксис метода forEach() следующий:

arr.forEach(function callback(item, index, array) {


// выполняем действия с текущим элементом массива
}, thisArg);

callback- функция, которую необходимо выполнить для каждого элемента


массива. Эта функция принимает три параметра:

3.2. Методы массивов 2


- item (значение текущего элемента),

- index (индекс текущего элемента)


- array (сам массив).

thisArg (опциональный) - значение, которое будет использоваться в качестве


this внутри функции callback .

Пример использования метода forEach() :

const arr = [1, 2, 3];

const result = arr.forEach(item => {


console.log(item);
});

console.log(result); // undefined

// Вывод в консоль
// 1
// 2
// 3

В этом примере forEach() выполняет функцию callback для каждого элемента


массива arr , и функция выводит значение каждого элемента в консоль.
Метод forEach() не возвращает новый массив, но позволяет модифицировать
текущий массив. Если функция callback возвращает значение, это значение
будет проигнорировано и не влияет на элементы массива.

Одним из преимуществ метода forEach() является то, что он облегчает чтение и


понимание кода. Также метод forEach() может быть полезен, когда необходимо
выполнить определенные операции для каждого элемента массива. Однако, если
необходимо изменить или фильтровать элементы массива, другие методы
массива, такие как map() , filter() , или reduce() , могут оказаться более удобными.

map()
Метод массива map() является одним из наиболее полезных методов. Он
позволяет применять функцию к каждому элементу массива и возвращать новый
массив с результатами. Это очень мощный инструмент, который может быть
использован для трансформации данных и упрощения кода.

3.2. Методы массивов 3


arr.map(function callback(item, index, array) {
// выполняем действия с текущим элементом массива и возвращаем его
}, thisArg);

callback- функция, которую необходимо выполнить для каждого элемента


массива. Эта функция принимает три параметра:
- item (значение текущего элемента),

- index (индекс текущего элемента)


- array (сам массив).

thisArg (опциональный) - значение, которое будет использоваться в качестве


this внутри функции callback .

Вот основные принципы работы метода map() :

1. map() создает новый массив. Он не изменяет исходный массив.

2. map()принимает функцию обратного вызова, которая применяется к каждому


элементу массива.

4. Функция обратного вызова возвращает новое значение, которое будет


добавлено в новый массив.

5. Метод map() возвращает новый массив с результатами.

Вот пример использования метода map() для удвоения всех элементов массива:

const arr = [1, 2, 3, 4, 5];


const doubledArr = arr.map((item) => item * 2);
console.log(doubledArr); // [2, 4, 6, 8, 10]

В этом примере метод map() создает новый массив doubledArr , который содержит
результат удвоения каждого элемента исходного массива arr . Функция обратного
вызова, переданная в метод map() , просто умножает каждый элемент на 2 и
возвращает новое значение.
map() может быть использован для выполнения любых операций, которые можно
выполнить с каждым элементом массива. Он также может быть использован для

3.2. Методы массивов 4


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

filter()
Метод массива filter() используется для создания нового массива из исходного
массива, содержащего только те элементы, которые удовлетворяют условие
заданном в callback-функции.

arr.filter(function callback(item, index, array) {


// условие
}, thisArg);

callback- функция, которую необходимо выполнить для каждого элемента


массива. Эта функция принимает три параметра:

- item (значение текущего элемента),

- index (индекс текущего элемента)

- array (сам массив).

thisArg (опциональный) - значение, которое будет использоваться в качестве


this внутри функции callback .

Функция обратного вызова должна вернуть булево значение true или false ,
чтобы указать, должен ли элемент быть включен в новый массив.

Пример использования метода filter() для фильтрации массива:

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const evenNumbers = numbers.filter((item) => {


return item % 2 === 0;
});

console.log(evenNumbers); // [2, 4, 6, 8, 10]

В этом примере мы создали новый массив evenNumbers , содержащий только четные


числа из исходного массива numbers .

3.2. Методы массивов 5


Метод filter() не изменяет исходный массив, а возвращает новый массив,
содержащий отфильтрованные элементы. Если ни один элемент массива не
удовлетворяет условие , то возвращаемый массив будет пустым.

find()
Метод find() возвращает первый элемент массива, который удовлетворяет
условию, заданному в переданной ему callback-функции. Если в массиве не
найден ни один элемент, удовлетворяющий условию, метод find() возвращает
undefined .

Синтаксис метода find() выглядит следующим образом:

arr.find(function callback(item, index, array) {


// условие
}, thisArg);

где:

callback- функция, которую необходимо выполнить для каждого элемента


массива. Эта функция принимает три параметра:

- item (значение текущего элемента),


- index (индекс текущего элемента)

- array (сам массив).

thisArg (опциональный) - значение, которое будет использоваться в качестве


this внутри функции callback .

Функция callback должна вернуть true , если элемент соответствует условию


поиска, и false в противном случае.

Пример использования метода find() :

const numbers = [1, 2, 3, 4, 5];


const evenNumber = numbers.find(num => num % 2 === 0);
console.log(evenNumber); // 2

3.2. Методы массивов 6


В данном примере метод find() ищет первый четный элемент в массиве numbers и
возвращает его значение.

sort()
Метод sort() позволяет сортировать элементы массива и изменять порядок их
расположения. Метод сортирует элементы массива на месте, то есть не создает
новый отсортированный массив, а изменяет порядок элементов в исходном
массиве.

Синтаксис метода:

array.sort([compareFunction])

(необязательный параметр) - функция сравнения, которая


compareFunction

определяет порядок сортировки. Если compareFunction не указана, то метод


сортирует элементы массива как строки в порядке возрастания (согласно кодам
символов Unicode).
Функция сравнения может принимать два аргумента - a и b , которые являются
элементами массива, и возвращает число, определяющее порядок сравниваемых
элементов:

Если функция возвращает отрицательное число, то a будет расположено


перед b .

Если функция возвращает положительное число, то b будет расположено


перед a .

Если функция возвращает ноль, то порядок элементов не изменится.

Примеры:

1. Сортировка чисел:

const numbers = [4, 2, 7, 1, 9];


numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 4, 7, 9]

//то же самое но длинный вариант


numbers.sort((a, b) => {
if (a > b) { return 1; }

3.2. Методы массивов 7


if (a < b) { return -1; }
if (a === b) { return 0; }
});
console.log(numbers); // [1, 2, 4, 7, 9]

2. Сортировка строк:

const fruits = ['apple', 'banana', 'orange', 'grape'];


fruits.sort();
console.log(fruits); // ['apple', 'banana', 'grape', 'orange']

По Unicode сортирует строки (для нас это выглядит как по алфавиту)

3. Сортировка объектов:

const students = [
{ name: 'Pavel', grade: 8 },
{ name: 'Roma', grade: 7 },
{ name: 'Katya', grade: 9 },
];

students.sort((a, b) => a.grade - b.grade);


console.log(students); // [{ name: 'Roma', grade: 7 }, { name: 'Pavel', grade: 8 }, { nam
e: 'Katya', grade: 9 }]

Обратите внимание, что метод sort() изменяет порядок элементов в исходном


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

const numbers = [4, 2, 7, 1, 9];


const sortedNumbers = [...numbers].sort((a, b) => a - b);
console.log(numbers); // [4, 2, 7, 1, 9]
console.log(sortedNumbers); // [1, 2, 4, 7, 9]

reduce()
Метод reduce() используется для преобразования массива в единое значение
(число, строку, объект и т.д.), путем применения функции к каждому элементу
массива и аккумуляции результата (накопления).

Синтаксис метода reduce() выглядит следующим образом:

3.2. Методы массивов 8


array.reduce(callback, initialValue)

- функция, которая будет применяться к каждому элементу массива.


callback

Она принимает в себя четыре аргумента: аккумулятор (prev), текущий


элемент (item), текущий индекс (index) и сам массив (array).

initialValue (необязательный параметр) - значение, которое будет


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

Пример использования метода reduce() :

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((prev, item) => prev + item);


const result = numbers.reduce((prev, item) => prev + item,"");

console.log(sum); // 15
console.log(result); // "12345"

В этом примере метод reduce() используется для вычисления суммы элементов


массива numbers . Функция обратного вызова принимает два аргумента: prev
(начальное значение равно первому элементу массива) и curr (текущий элемент
массива). В каждой итерации значения prev и curr суммируются, и результат
сохраняется в prev . В конце выполнения метода reduce() возвращается
окончательное значение prev .

indexOf()
Метод массива indexOf() возвращает индекс первого вхождения заданного
элемента в массиве или -1, если элемент не найден.
Синтаксис метода:

arr.indexOf(searchElement[, fromIndex])

где:

3.2. Методы массивов 9


searchElement - элемент, который нужно найти в массиве;

fromIndex (необязательный) - индекс, с которого начинать поиск. Если не


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

Метод indexOf() сравнивает каждый элемент массива с searchElement с помощью


строгого равенства ( === ), начиная с индекса fromIndex (или с начала массива, если
не указан). Если находится элемент, равный searchElement , метод
fromIndex

возвращает его индекс. Если элемент не найден, метод возвращает -1.

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

const fruits = ['apple', 'banana', 'orange', 'pear'];

console.log(fruits.indexOf('banana')); // 1
console.log(fruits.indexOf('pear', 2)); // 3
console.log(fruits.indexOf('grape')); // -1

В первом примере метод indexOf() находит элемент "banana" в массиве fruits и


возвращает его индекс 1.

Во втором примере метод начинает поиск с индекса 2, который соответствует


элементу "orange". Это означает, что поиск элемента "pear" будет осуществляться
с третьего элемента массива, а не с начала. B последней консоли мы увидим -1
потому что в массиве нет “grape”.

includes()
Метод массива includes() - это метод JavaScript, который используется для
определения, содержит ли массив определенный элемент, и возвращает
логическое значение true или false.
Синтаксис метода includes():

array.includes(searchElement, fromIndex)

searchElement - элемент, который нужно найти в массиве

(необязательный) - индекс массива, с которого начинается поиск


fromIndex

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

3.2. Методы массивов 10


Метод includes() использует строгое сравнение (===) для сравнения элементов
массива с искомым элементом.

Возвращаемое значение: true, если элемент найден в массиве, и false, если


элемент не найден.
Например:

const array = [1, 2, 3, 4, 5];


console.log(array.includes(3)); // true
console.log(array.includes(6)); // false

Метод includes() также может использоваться для поиска строк в массивах строк:

const array = ['apple', 'banana', 'orange'];


console.log(array.includes('banana')); // true
console.log(array.includes('grape')); // false

splice()
Метод splice() позволяет изменять содержимое массива путем удаления или
замены существующих элементов и/или добавления новых элементов.

Синтаксис метода splice() :

array.splice(start, deleteCount, item1, item2, ...)

Параметры:

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


отрицательное число, то индекс будет отсчитываться с конца массива
(например, -1 означает последний элемент массива).

deleteCount(опционально): Число элементов, которые необходимо удалить


начиная с start . Если не задано, все элементы, начиная с start , будут
удалены.

item1, item2, ... (опционально): Элементы, которые нужно добавить в массив


начиная с индекса start .

3.2. Методы массивов 11


Возвращаемое значение: возвращает массив из удаленных элементов. Если
ни один элемент не был удален, метод возвращает пустой массив [] .
Примеры использования:

1. Удаление элементов из массива:

const fruits = ['apple', 'banana', 'cherry', 'date'];

// удалить два элемента начиная с индекса 1 (banana и cherry)


const deletedFruits = fruits.splice(1, 2);

console.log(fruits); // ["apple", "date"]


console.log(deletedFruits); // ["banana", "cherry"]

2. Замена элементов в массиве:

const fruits = ['apple', 'banana', 'cherry', 'date'];

// заменить два элемента начиная с индекса 1 (banana и cherry) на элементы "lemon" и "lim
e"
fruits.splice(1, 2, "lemon", "lime");

console.log(fruits); // ["apple", "lemon", "lime", "date"]

3. Добавление элементов в массив:

const fruits = ['apple', 'banana', 'cherry', 'date'];

// добавить два элемента начиная с индекса 1 (между apple и banana)


fruits.splice(1, 0, "apricot", "blueberry");

console.log(fruits); // ["apple", "apricot", "blueberry", "banana", "cherry", "date"]

то есть можно не удалять элементы, а вставлять нужные в любое место массива.

join()
Метод join() используется для объединения всех элементов массива в одну
строку.
Синтаксис метода выглядит следующим образом:

3.2. Методы массивов 12


array.join(separator)

где separator - это необязательный параметр, который указывает разделитель


между элементами массива в результирующей строке. Если параметр не указан,
то в качестве разделителя используется запятая.
Вот несколько примеров использования метода join() :

const arr = ['один', 'два', 'три'];

const result0 = arr.join(); // 'один,два,три'


const result1 = arr.join(''); // 'одиндватри'
const result2 = arr.join('-'); // 'один-два-три'
const result3 = arr.join(' '); // 'один два три'

Надо учитывать, что метод join() не изменяет исходный массив, а возвращает


новую строку, созданную из элементов массива.

reverse()
Метод reverse() изменяет порядок элементов в массиве на обратный. Это
означает, что первый элемент становится последним, второй - предпоследним и
так далее, а последний элемент становится первым.

Синтаксис метода reverse() выглядит следующим образом:

array.reverse();

Здесь array - это массив, который мы хотим изменить. Метод reverse() не


принимает никаких аргументов.
Пример использования метода reverse() :

const arr = ['one', 'two', 'three', 'four'];


arr.reverse();
console.log(arr); // ['four', 'three', 'two', 'one']

3.2. Методы массивов 13


В этом примере мы создаем массив arr , затем вызываем на нем метод reverse() ,
который изменяет порядок элементов в массиве. Затем мы выводим измененный
массив в консоль.

Важно отметить, что метод reverse() изменяет исходный массив, а не создает


новый массив. Поэтому, если вы хотите сохранить исходный порядок элементов в
массиве, вам следует создать копию массива перед вызовом метода reverse() .
reverse() возвращает ссылку на исходный массив.

fill()
Метод fill() массива в JavaScript используется для заполнения всех элементов
массива одним и тем же значением. Он изменяет исходный массив, а не создает
новый массив.

Синтаксис метода fill() выглядит так:

array.fill(value, start, end)

value : Значение, которым нужно заполнить массив. Обязательный параметр.

: Необязательный параметр, определяет индекс начала заполнения


start

элементами. Значение по умолчанию - 0.

end: Необязательный параметр, определяет индекс, до которого нужно


заполнить элементами. Значение по умолчанию - длина массива.

Метод fill() изменяет все элементы массива, начиная с индекса start и


заканчивая индексом end не включая, на значение value .
Вот несколько примеров использования метода fill() :

const arr1 = [1, 2, 3, 4, 5];


arr1.fill(0); // arr1 теперь равен [0, 0, 0, 0, 0]

const arr2 = [1, 2, 3, 4, 5];


arr2.fill(0, 1, 4); // arr2 теперь равен [1, 0, 0, 0, 5]

const arr3 = new Array(3);


arr3.fill('default'); // arr3 теперь равен ['default', 'default', 'default']

3.2. Методы массивов 14


Здесь первый пример заполняет все элементы массива arr1 значением 0. Второй
пример заполняет элементы массива arr2 значением 0, начиная с индекса 1 и
заканчивая индексом 4 (не включая его). Третий пример создает массив arr3 с
тремя пустыми ячейками и затем заполняет их значением "default".
Также метод fill() может использоваться с отрицательными индексами, что
позволяет заполнить элементы массива, начиная с конца:

const arr4 = [1, 2, 3, 4, 5];


arr4.fill(0, -2); // arr4 теперь равен [1, 2, 3, 0, 0]

Здесь метод fill() заполняет два последних элемента массива arr4 значением 0,
начиная с индекса -2 (предпоследнего элемента массива).

push()
Метод push() - позволяет добавлять один или несколько элементов в конец
массива. Синтаксис метода push() выглядит следующим образом:

array.push(element1, ..., elementN);

Здесь array - это массив, в который нужно добавить элементы, а element1, ...,
elementN - это элементы, которые нужно добавить. Метод push() изменяет

исходный массив и возвращает новую длину массива после добавления


элементов.

Например:

const fruits = ['яблоко', 'банан', 'апельсин'];


const newLength = fruits.push('груша', 'киви');
console.log(fruits); // ['яблоко', 'банан', 'апельсин', 'груша', 'киви']
console.log(newLength); // 5

В этом примере мы объявляем массив fruits , содержащий несколько элементов.


Затем мы используем метод push() , чтобы добавить два новых элемента - 'груша'
и 'киви' - в конец массива. Метод push() изменяет массив fruits и возвращает
новую длину массива, которая в данном случае равна 5.

3.2. Методы массивов 15


pop()
Метод pop() - удаляет последний элемент из массива и возвращает его значение.
Он изменяет исходный массив, уменьшая его длину на один элемент.

Вот несколько важных фактов о методе pop() :

1. Синтаксис: array.pop() , где array - это массив, с которым ты работаешь.

2. Если массив пустой, метод pop() возвращает undefined .

3. Метод pop() не принимает аргументов и не изменяет порядок элементов в


массиве, кроме удаления последнего элемента.

4. Метод pop() является обратным методу push() , который добавляет элементы


в конец массива.

5. Метод pop() можно использовать для реализации стека, который использует


принцип "последний вошел - первый вышел" (LIFO).

Вот пример использования метода pop() :

const myArray = ['apple', 'banana', 'cherry'];


const lastItem = myArray.pop(); // удалить последний элемент (cherry) и сохранить его в пе
ременной lastItem
console.log(myArray); // ['apple', 'banana']
console.log(lastItem); // 'cherry'

В этом примере мы используем метод pop() для удаления последнего элемента из


массива myArray и сохранения его в переменной lastItem .

shift()
shift() - это метод массива в JavaScript, который удаляет первый элемент из
массива и возвращает его значение. Если массив пустой, то метод shift() вернет
undefined . Метод shift() также изменяет длину массива, удаляя первый элемент

из массива.

Вот пример использования метода shift() :

const numbers = [1, 2, 3, 4];


const firstNumber = numbers.shift();

3.2. Методы массивов 16


console.log(numbers); // [2, 3, 4]
console.log(firstNumber); // 1

В этом примере мы создали массив numbers с четырьмя элементами, а затем


вызвали метод shift() на массиве numbers . Метод shift() удалил первый элемент
массива 1 и вернул его значение, которое мы сохраняем в переменной
firstNumber .

Метод shift() изменяет исходный массив.

unshift()
Метод unshift() используется для добавления одного или нескольких элементов в
начало массива.
Синтаксис метода unshift() выглядит следующим образом:

arr.unshift(element1, element2, ..., elementN);

где arr - массив, в который необходимо добавить элементы, а element1, element2,

..., elementN - элементы, которые будут добавлены в начало массива.

Метод unshift() изменяет исходный массив и возвращает новую длину массива


после добавления элементов.

Некоторые особенности метода unshift() :

Элементы добавляются в начало массива, то есть индексы всех


существующих элементов в массиве сдвигаются на один вправо.

Метод unshift() возвращает новую длину массива после добавления


элементов, то есть сумму длины исходного массива и количества
добавленных элементов.

Метод unshift() может принимать неограниченное количество аргументов.

Пример использования метода unshift() :

const arr = [1, 2, 3];


const newLength = arr.unshift(0, -1);
console.log(arr); // [0, -1, 1, 2, 3]
console.log(newLength); // 5

3.2. Методы массивов 17


В этом примере мы создали массив [1, 2, 3] и использовали метод unshift() для
добавления элементов 0 и -1 в начало массива. Метод unshift() вернул новую
длину массива ( 5 ), а массив был изменен и теперь имеет вид [0, -1, 1, 2, 3] .
То есть пока знаем 4 метода. 2 их них работают с началом массива, а 2 с концом.
При этом они все изменяют исходный массив.
Продолжим….

flat()
Метод flat() создает новый массив, в котором все подмассивы в исходном
массиве выровнены в один уровень глубины. То есть, если исходный массив
содержит вложенные массивы, метод flat() "разворачивает" их, превращая
многомерный массив в одномерный.

Метод flat() может принимать необязательный аргумент, указывающий глубину,


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

Пример использования метода flat() :

const arr = [1, 2, [3, 4, [5, 6]]];


const flattenedArr = arr.flat();
console.log(flattenedArr); // [1, 2, 3, 4, [5, 6]]

const deeplyFlattenedArr = arr.flat(Infinity);


console.log(deeplyFlattenedArr); // [1, 2, 3, 4, 5, 6]

В примере выше, исходный массив arr содержит вложенные массивы. Вызов


метода flat() без аргументов выравнивает только первый уровень подмассивов,
поэтому массив flattenedArr содержит первые два элемента массива arr и
выровненный подмассив [3, 4, [5, 6]] . Вызов метода flat(Infinity) выравнивает
все вложенные массивы и возвращает одномерный массив deeplyFlattenedArr .
Метод flat() не изменяет исходный массив, а возвращает новый массив с
выровненными элементами. Если в исходном массиве нет подмассивов, метод
flat() вернет копию исходного массива.

3.2. Методы массивов 18


findIndex()
Метод массива findIndex() используется для поиска индекса первого элемента в
массиве, который удовлетворяет условию, заданному в виде callback-функции.
Если ни один элемент не удовлетворяет условию, метод вернет -1 .
Синтаксис метода выглядит следующим образом:

array.findIndex(callback(item, index, array), thisArg)

callback- функция, которая вызывается для каждого элемента массива.


Функция должна возвращать true , если элемент удовлетворяет заданному
условию, иначе - false .

item - текущий элемент массива.

index (необязательный) - индекс текущего элемента в массиве.

array (необязательный) - исходный массив.

thisArg (необязательный) - значение, которое будет использоваться в качестве


this при вызове функции callback .

Пример использования метода findIndex() :

const array = [2, 5, 8, 1, 4];


const index = array.findIndex((item) => element > 4);
console.log(index); // 1

В этом примере метод findIndex() вызывается на массиве array с функцией


обратного вызова, которая проверяет, больше ли текущий элемент 4. Так как
первый элемент, который удовлетворяет этому условию, имеет индекс 1, метод
возвращает значение 1.

every()
Метод every() принимает callback-функцию и проверяет, удовлетворяет ли
каждый элемент массива условию, заданному этой функцией. Если каждый
элемент массива удовлетворяет этому условию, то метод возвращает true . Если
хотя бы один элемент не удовлетворяет условию, то метод возвращает false .

3.2. Методы массивов 19


Синтаксис метода every() выглядит следующим образом:

arr.every(callback[, thisArg])

Здесь arr - это массив, на котором вызывается метод every() , callback - это
функция обратного вызова, которая будет вызвана для каждого элемента массива,
и thisArg - это значение, которое будет использовано в качестве this при вызове
функции callback .

Функция callback принимает три аргумента: item , index и array . item - это
текущий элемент массива, index - это индекс текущего элемента, а array - это сам
массив, на котором вызывается метод every() .
Вот несколько примеров использования метода every() :

// Проверяем, все ли элементы массива больше 0


const arr1 = [1, 2, 3, 4];
const result1 = arr1.every((element) => element > 0);
console.log(result1); // true

// Проверяем, все ли элементы массива четные


const arr2 = [2, 4, 6, 7];
const result2 = arr2.every((element) => element % 2 === 0);
console.log(result2); // false

В первом примере метод every() возвращает true , потому что все элементы
массива arr1 больше 0. Во втором примере метод every() возвращает false ,
потому что один из элементов массива arr2 (число 7) не является четным.

some()
Метод some() используется для проверки того, соответствует ли хотя бы один
элемент массива заданному условию. Метод возвращает булевое значение true ,
если условие истинно для хотя бы одного элемента массива, и false , если это не
так.
Синтаксис метода some() выглядит следующим образом:

array.some(callback[, thisArg])

3.2. Методы массивов 20


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

Функция callback принимает три аргумента: item , index и array . item - это
текущий элемент массива, index - это индекс текущего элемента, а array - это сам
массив, на котором вызывается метод every() .

Функция обратного вызова callback должна возвращать булевое значение true ,


если условие выполняется для текущего элемента, и false в противном случае.
Например, следующий код проверяет, содержит ли массив numbers хотя бы одно
четное число:

const numbers = [1, 2, 3, 4, 5];


const hasEven = numbers.some((number) => number % 2 === 0);
console.log(hasEven); // true

Метод some() особенно полезен при работе с большими массивами, когда нужно
быстро определить, есть ли в них элементы, удовлетворяющие заданному
условию.

concat()
Метод concat() в JavaScript используется для объединения двух или более
массивов в один новый массив. Он не изменяет исходные массивы, а возвращает
новый массив, содержащий все элементы исходных массивов в порядке их
следования.
Синтаксис метода concat() выглядит следующим образом:

newArray = array1.concat(array2, array3, ..., arrayN);

где array1 - массив, в который будут добавлены другие массивы, array2 , array3 ,
..., arrayN - массивы, которые нужно добавить в array1 . Метод concat() может
принимать любое количество аргументов массивов.

Например, для объединения двух массивов array1 и array2 можно использовать


следующий код:

3.2. Методы массивов 21


const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const newArray = array1.concat(array2);
console.log(newArray); // [1, 2, 3, 4, 5, 6]

Если метод concat() вызывается без аргументов, то он возвращает копию


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

const array1 = [1, 2, 3];


const array2 = [4, 5, 6];
const array3 = [7, 8, 9];
const newArray = array1.concat(array2, array3);
console.log(newArray); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

slice()
Метод массива slice() используется для создания нового массива, содержащего
выбранные элементы из исходного массива. Он не изменяет исходный массив,
а возвращает новый массив, который может быть сохранен в переменной или
использован для дальнейшей обработки.

Синтаксис метода slice() выглядит следующим образом:

arr.slice(start, end);

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


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

Если start не указан, то извлечение начинается с индекса 0. Если end не указан,


то извлечение продолжается до конца массива.
Например, следующий код создает новый массив, содержащий элементы с
индексами от 2 до 5 не включительно из исходного массива arr :

3.2. Методы массивов 22


const arr = [0, 1, 2, 3, 4, 5];
const newArr = arr.slice(2, 5);
console.log(newArr); // [2, 3, 4]

Если start больше, чем индекс последнего элемента в массиве, то slice() вернет
пустой массив. Если end меньше, чем start , то также будет возвращен пустой
массив.
Метод slice() также может использоваться для создания копии массива. Для
этого достаточно вызвать slice() без аргументов:

const arr = [0, 1, 2, 3, 4, 5];


const newArr = arr.slice();
console.log(newArr); // [0, 1, 2, 3, 4, 5]

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

Доп.
8 методов которые изменяют исходный массив.

push , pop , shift , unshift , splice , sort , reverse , fill

Задания
1. Напиши функцию, которая принимает массив строк и возвращает новый
массив, в котором каждая строка записана в верхнем регистре.

2. Напиши функцию, которая принимает массив объектов с полями name и age и


возвращает новый массив, в котором каждый объект имеет дополнительное
поле greeting , содержащее строку вида "Привет, {name} ({age})!".

3. Напиши функцию, которая принимает массив чисел и возвращает новый


массив, в котором каждый элемент преобразован в строку и добавлен префикс
"Number: ".

3.2. Методы массивов 23


4. Напиши функцию, которая принимает массив строк и возвращает новый
массив, в котором каждая строка обрезана до первых трех символов.

5. Напиши функцию, которая принимает массив и возвращает новый массив из


всех элементов, которые являются числами.

6. Напиши функцию, которая принимает массив и возвращает новый массив из


всех элементов в массиве, которые имеют четный индекс.

7. Напиши функцию, которая принимает массив объектов и возвращает новый


массив из всех объектов в массиве, у которых свойство age больше 18.

8. Напиши функцию, которая принимает массив и возвращает новый массив из


всех строк в массиве, которые содержат букву 'a'.

9. Напиши функцию, которая принимает массив и возвращает новый массив из


всех чисел в массиве, которые больше 10.

10. Отсортировать массив объектов по возрастанию значения свойства age .

const people = [
{ name: 'Pavel', age: 25 },
{ name: 'Alex', age: 20 },
{ name: 'Irina', age: 30 },
];

12. Напиши функцию, которая принимает массив строк. Посчитать количество


повторений каждого элемента в массиве.

const array = ["a","b","c","b","a","b"];

const counter = (arr)=> {};

counter(array); // "a:2, b:3, c:1"

13. Напиши функцию, которая принимает массив чисел и разделяет массив на две
группы: четные и нечетные {even:[], odd:[]} (через reduce)

14. Все задачи в колонке “Задачи”

3.2. Методы массивов 24


Помоги сделать эту эту главу лучше! Дай обратную связь, а мы
прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/HrWQ7pSzA2piJ4tY6

☔ 4.1. ДП + spread

3.2. Методы массивов 25



4.1. ДП + spread
ДП - деструктурирующее присваивание -
деструктуризация
Деструктуризация - это синтаксическая конструкция, которая позволяет
извлекать значения из массивов или объектов и сохранять их в переменные.

Деструктуризация массива
Деструктуризация массива - это процесс извлечения значений из массива и
присваивания их переменным.

Пример:

const myArray = [1, 2, 3];


const [a, b, c] = myArray;

console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

В этом примере создается массив myArray с тремя элементами. Затем


используется синтаксис деструктуризации, чтобы присвоить значения переменным
a, b и c.

Rest (…) - это оператор, который позволяет нам собрать все оставшиеся
элементы массива в одну переменную.
Пример использования rest:

const myArray = [1, 2, 3, 4, 5];


const [a, b, ...rest] = myArray;

console.log(a); // 1

4.1. ДП + spread 1
console.log(b); // 2
console.log(rest); // [3, 4, 5]

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


значения первым двум элементам массива - переменным a и b . Затем
используется оператор rest ( ...rest ), чтобы собрать все оставшиеся элементы
массива в одну переменную rest .
Сама переменная rest не обязательно должна называться так, но она
обязательно должна стоят в конце, иначе будет ошибка
SyntaxError: Rest element must be last element

const myArray = [1, 2, 3, 4, 5];


const [a, b, ...ostatok] = myArray; // так можно
const [a, ...ostatok, b] = myArray; // так нельзя и будет ошибка

console.log(a); // 1
console.log(b); // 2
console.log(ostatok); // [3, 4, 5]

Так же для переменных можно задавать значение по


умолчанию.
Значение по умолчанию - это значение, которое будет присвоено переменной,
если элемент в массиве отсутствует или равен undefined .

Пример использования значения по умолчанию в деструктуризации массива:

const myArray = [1, 2];


const [a, b, c = 3] = myArray;

console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

В этом примере создается массив myArray с двумя элементами. Затем


используется деструктуризация, чтобы присвоить значения первых двух
элементов массива переменным a и b . В качестве третьего элемента
используется значение по умолчанию, которое равно 3. Так как в массиве только

4.1. ДП + spread 2
два элемента, то переменной c будет присвоено значение по умолчанию. Если
бы значения по умолчанию не было, то c была бы равна undefined .

Для пропуска нескольких элементов при деструктуризации массива можно


использовать запятые.
Пример:

const myArray = [1, 2, 3, 4, 5];

const [a, , , d, e] = myArray;

console.log(a); // 1
console.log(d); // 4
console.log(e); // 5

В этом примере есть массив myArray с пятью элементами. Затем используется


деструктуризация, чтобы присвоить значения первого, четвертого и пятого
элементов массива переменным a , d и e соответственно. Для пропуска второго
и третьего элементов массива используются запятые.

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

const myObject = {name: "Pavel", age: 25};


const {name, age} = myObject;

console.log(name); // "Pavel"
console.log(age); // 25

В этом примере создается объект myObject с двумя свойствами - name и age . Затем
используется деструктуризация объекта, чтобы присвоить значения этих свойств
переменным name и age .

4.1. ДП + spread 3
Кроме того, при деструктуризации объекта можно использовать значение по
умолчанию, которое будет присвоено переменной, если свойство объекта
отсутствует.

Пример использования значения по умолчанию при деструктуризации объекта:

const myObject = {name: "Pavel"};

const {name, age = 25} = myObject;

console.log(name); // "Pavel"
console.log(age); // 25

В этом примере опять же используется деструктуризация объекта, чтобы


присвоить значения свойств объекта переменным name и age . Так как свойство
age отсутствует в объекте myObject , то переменной age будет присвоено значение

по умолчанию, равное 25.

Также, при деструктуризации объекта можно использовать оператор rest, который


позволяет собрать в объекте все не использованные свойства.

Пример использования оператора rest при деструктуризации объекта:

const myObject = {name: "Pavel", age: 25, city: "Minsk"};

const {name, ...rest} = myObject;

console.log(name); // "Pavel"
console.log(rest); // {age: 25, city: "Minsk"}

В этом примере мы использовали оператор rest ( ...rest ), чтобы собрать все


оставшиеся свойства объекта в один объект rest . Таким образом, переменной
name будет присвоено значение свойства name объекта myObject , а переменной

rest - объект со свойствами age и city .

Для переименования свойств объекта при деструктуризации можно использовать


двоеточие после имени свойства, а затем задать новое имя переменной.

Пример:

4.1. ДП + spread 4
const myObject = {name: "Pavel", age: 25};

const {name: fullName, age: userAge} = myObject;

console.log(fullName); // "Pavel"
console.log(userAge); // 25

В этом примере создается объект myObject с двумя свойствами - name и age . Затем
используется деструктуризация объекта, чтобы присвоить значения свойств
объекта переменным fullName и userAge , переименовав при этом свойства
объекта.
Таким образом, свойство name объекта myObject было переименовано в
переменную fullName , а свойство age - в переменную userAge .

Деструктуризация строки
Деструктуризация строки - это процесс извлечения отдельных символов или
подстрок из строки в JavaScript.
Вот несколько примеров использования деструктуризации строки в JavaScript:

1. Извлечение первого символа строки:

const str = 'hello';


const [firstChar] = str;
console.log(firstChar); // 'h'

2. Извлечение символов с определенными индексами:

const str = 'hello';


const [, secondChar, , fourthChar] = str;
console.log(secondChar); // 'e'
console.log(fourthChar); // 'l'

Деструктуризация строки позволяет более элегантно и компактно работать с


символами и подстроками в JavaScript.

4.1. ДП + spread 5
Деструктуризация может быть полезна в
следующих случаях:
1. Передача параметров в функцию. Деструктуризация может быть
использована для передачи объекта в функцию и извлечения его свойств в
качестве параметров. Это удобно, когда нужно передать только определенные
свойства объекта в функцию.

function greetUser({name, age}) {


console.log(`Hello, ${name}! You are ${age} years old.`);
}

const user = {name: "Pavel", age: 25};


greetUser(user); // "Hello, Pavel! You are 25 years old."

2. Объявление переменных. Деструктуризация позволяет объявить несколько


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

const array = [1, 2, 3, 4, 5, 6, 7];


const [first, second] = array;
console.log(first); // 1
console.log(second); // 2

const obj = {name: "Pavel", age:25, isMan: true};


const {age, name} = obj;
console.log(name); // "Pavel"
console.log(age); // 25

3. Извлечение значений из вложенных объектов или массивов.


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

const user = {
name: "Pavel",
age: 25,
address: {
city: "Minsk'",

4.1. ДП + spread 6
country: "Belarus",
},
};

const {name, address: {city}} = user;


console.log(name); // "Pavel"
console.log(city); // "Minsk"

4. Переименование свойств объекта:

const person = {
firstName: 'Pavel',
lastName: 'Hutsu'
};

const { firstName: name, lastName: surname } = person;


console.log(name); // 'Pavel'
console.log(surname); // 'Hutsu'

5. Извлечение значений из Map:

const myMap = new Map();


myMap.set('key1', 'value1');
myMap.set('key2', 'value2');

for (const [key, value] of myMap) {


console.log(`${key} = ${value}`);
}
// Вывод:
// "key1 = value1"
// "key2 = value2"

Spread
Оператор spread ( ... ) - это удобный способ для копирования массивов и
объектов, а также для объединения нескольких массивов и объектов в один.

1. С массивами, оператор spread позволяет создавать новый массив,


содержащий все элементы исходного массива. Он делает ПОВЕРХНОСТНУЮ
копию объекта/массива. Например, если у тебя есть массив arr1 , можно
создать новый массив, содержащий все элементы arr1 , используя следующий
синтаксис:

4.1. ДП + spread 7
const arr1 = [1,2,3];
const arr2 = [...arr1];

console.log(arr2); // [1,2,3]

2. Также, оператор spread может использоваться для объединения нескольких


массивов в один. Например, если у вас есть массивы arr1 и arr2 , вы можете
создать новый массив, содержащий все элементы обоих массивов, используя
следующий синтаксис:

const arr1 = [1,2,3];


const arr2 = [4,5,6];
const arr3 = [...arr1, ...arr2];

console.log(arr3); // [1,2,3,4,5,6]

3. С объектами, оператор spread позволяет создавать новый объект,


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

const obj1 = {name:"Pavel"};


const obj2 = {...obj1};

console.log(obj2); // {name:"Pavel"}

4. Также, оператор spread может использоваться для создания нового объекта с


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

const obj1 = {name:"Pavel", age: 25};


const obj2 = {...obj1, age:26};

console.log(obj2); // {name:"Pavel", age:26}

4.1. ДП + spread 8
В этом примере, obj2 будет содержать все свойства obj1 , но со значением
свойства age , измененным на 26 .

Задания
Задания для закрепления темы деструктуризации с массивами:

1. Создай массив с элементами [1, 2, 3, 4, 5] . Используя деструктуризацию,


присвой значения первых трёх элементов массива переменным a , b и c
соответственно.

2. Создай массив с элементами [1, 2, 3, 4, 5] . Используя деструктуризацию,


пропусти первые два элемента массива, а затем присвой значения следующих
двух элементов переменным a и b соответственно.

3. Создай массив с элементами [1, 2, 3, 4, 5] . Используя деструктуризацию,


присвой значение последнего элемента массива переменной a .

4. Создай массив с элементами [1, 2, 3, 4, 5] . Используя деструктуризацию,


присвой значения первых двух элементов массива переменным a и b ,а
оставшиеся элементы собери в массив rest .

5. Создай массив с элементами [1, 2, 3, 4, 5] . Используя деструктуризацию,


присвой значения первых двух элементов массива переменным a и b , а
оставшиеся элементы проигнорируй.

Задания для закрепления темы деструктуризации с объектами:

1. Создай объект myObject с двумя свойствами - name и age . Используя


деструктуризацию, присвой значение свойства name переменной a , а
значение свойства age переменной b .

2. Создай объект myObject с одним свойством - name . Используя


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

3. Создай объект myObject с тремя свойствами - name , age и city . Используя


деструктуризацию, присвой значения свойств name и age переменным a и b

соответственно, а все остальные свойства объекта проигнорируй.

4.1. ДП + spread 9
4. Создай объект myObject с полями name , age , city и country . Используя
деструктуризацию, присвой значения полям name , age и city переменным

, userAge и userCity соответственно, а поле country присвой


userName

переменной userCountry с помощью значения по умолчанию "Belarus".

Задания для закрепления темы SPREAD:

1. Напиши функцию, которая принимает два массива и объединяет их. Затем


отсортируй полученный массив и верни его.

2. Напиши функцию, которая принимает массив чисел и возвращает


максимальное число в этом массиве. Используй оператор spread для
передачи массива в Math.max().

3. Напиши функцию, которая принимает произвольное количество аргументов и


возвращает массив, содержащий эти аргументы.

4. Напиши функцию, которая принимает два объекта и возвращает новый объект,


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

5. Напиши функцию, которая принимает массив и возвращает новый массив с


уникальными значениями из первого массива.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/52fk9GAbrdQDrNd49

🧵 4.2. JSON

4.1. ДП + spread 10
🧵
4.2. JSON
JSON (JavaScript Object Notation) - это легкий формат обмена данными, который
используется для передачи и хранения структурированных данных между
клиентом и сервером.
В JavaScript, данные могут быть представлены в виде объектов и массивов. JSON
использует синтаксис, который очень похож на синтаксис объектов и массивов в
JavaScript, но существуют некоторые отличия.
JSON имеет следующие особенности:

JSON представляет данные в виде пар “ключ-значение”, где ключ - это строка
(а не строка и символ, как в объекте), а значение может быть любого типа,
включая объекты и массивы.

JSON не поддерживает комментарии, функции и некоторые другие


конструкции JavaScript.

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


объект JavaScript.

В JavaScript для работы с JSON используется объект JSON , который содержит два
метода:

JSON.stringify() : преобразует объект JavaScript в строку JSON.

JSON.parse() : преобразует строку JSON в объект JavaScript.

JSON.stringify()
Метод JSON.stringify() является одним из методов объекта JSON в JavaScript,
который преобразует объект JavaScript в строку JSON.
Синтаксис метода:

JSON.stringify(value, replacer, space);

4.2. JSON 1
value - это значение, которое нужно преобразовать в строку JSON.
replacer- это опциональный (необязательный) параметр, который позволяет
указать функцию, которая будет вызываться для каждого элемента объекта во
время преобразования. Функция получает два параметра: ключ и значение
текущего элемента объекта. Если функция возвращает undefined , элемент не
включается в результирующую JSON-строку. Если replacer является массивом, то
он должен содержать список свойств, которые нужно сериализовать.
space - опциональный параметр, который определяет количество пробелов или
символов табуляции для отступа в создаваемой строке JSON.

const user = {
name: 'Pavel',
age: 25,
isAdmin: true,
hobbies: ['eating', 'sleeping']
};

const jsonString = JSON.stringify(user);


console.log(jsonString);
console.log(typeof jsonString); // "string"

Результат будет выглядеть следующим образом:

`{"name":"Pavel","age":25,"isAdmin":true,"hobbies":["eating","sleeping"]}`

Метод JSON.stringify() может преобразовывать различные типы данных, такие как


строки, числа, логические значения, массивы и объекты. Кроме того, он может
преобразовывать значения null и undefined .
Метод JSON.stringify() не поддерживает сериализацию функций и некоторых
других значений, таких как Infinity , -Infinity и NaN . Если объект содержит такие
значения, они будут пропущены в результирующей строке JSON.

Затем мы можем использовать метод JSON.parse() (подробнее про него ниже) для
преобразования этой строки JSON обратно в объект JavaScript:

4.2. JSON 2
const jsonObject = JSON.parse(jsonString);
console.log(jsonObject);

Результат будет выглядеть так же, как и исходный объект:

{
name: 'Pavel',
age: 25,
isAdmin: true,
hobbies: ['eating', 'sleeping']
}

Пример с replacer и space

Вот пример использования JSON.stringify() с replacer и space :

const data = {
name: "Pavel",
age: 25,
hobbies: ['eating', 'sleeping'],
address: {
street: "Bratskaya",
city: "Minsk",
}
};

// использование функции в качестве replacer


const jsonString1 = JSON.stringify(data, (key, value) => {
if (key === "address") {
return undefined; // удаляем свойство "address" из JSON
}
return value;
}, 2); // используем 2 пробела для отступов

console.log(jsonString1);
/*
Вывод:
{
"name": "John",
"age": 30,
"hobbies": [
"reading",
"sports"
]
}
*/

4.2. JSON 3
// использование массива в качестве replacer
const jsonString2 = JSON.stringify(data, ["name", "hobbies"], 4); // используем 4 пробела
для отступов

console.log(jsonString2);
/*
Вывод:
{
"name": "Pavel",
"hobbies": [
"eating",
"sleeping"
]
}
*/

В первом примере свойство "address" удаляется из JSON с помощью функции в


качестве replacer . Второй пример использует массив свойств в качестве replacer
для сохранения только имени и хобби. В обоих примерах space задаёт количество
пробелов для отступов при форматировании JSON-строки.

JSON.parse()
- это метод, который позволяет преобразовывать строку JSON в
JSON.parse()

объект JavaScript. Этот метод может принимать строку JSON в качестве


параметра и возвращать соответствующий объект JavaScript.

Синтаксис метода выглядит следующим образом:

JSON.parse(text[, reviver])

Где text - это строка JSON, которую необходимо преобразовать в объект


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

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

4.2. JSON 4
Вот пример использования JSON.parse() с функцией reviver :

const text = '{"name":"Pavel","age":25,"city":"Minsk"}';


const obj = JSON.parse(text, (key, value) => {
if (key === 'age') {
return value + 5;
} else {
return value;
}
});

console.log(obj);
// {name: "Pavel", age: 30, city: "Minsk"}

В этом примере функция reviver увеличивает значение свойства age на 5,


оставляя другие свойства неизменными.

Если переданный текст не является строкой JSON, метод JSON.parse() выбросит


исключение SyntaxError . Также может быть выброшено исключение TypeError , если
переданный параметр text не является строкой.

Метод JSON.parse() также может обрабатывать объекты, содержащие даты,


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

Задания
1. Напиши функцию, которая принимает на вход JSON-строку с объектом и
возвращает количество свойств в объекте.

2. Напиши функцию, которая принимает на вход JSON-строку, содержащую


информацию о студентах (имя, возраст), и возвращает массив их имен.

3. Создай объект в формате JSON, который содержит информацию о погоде в


твоем городе на следующие 5 дней. Каждый день должен содержать
информацию о температуре, влажности и скорости ветра.

4. Напиши функцию, которая принимает на вход JSON-строку, содержащую


информацию о пользователях социальной сети, и возвращает список

4.2. JSON 5
пользователей, у которых более 1000 подписчиков.

5. Напиши функцию, которая принимает на вход JSON-строку, содержащую


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

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/GWykoZMQXqig6d2w6

⚠ 4.3. try…catch...finally

4.2. JSON 6

4.3. try…catch ...finally
try...catch...finally является конструкцией языка JavaScript, которая позволяет
обрабатывать ошибки во время выполнения кода.

Она позволяет предотвратить аварийное завершение программы при


возникновении ошибки и обеспечить контроль над дальнейшим выполнением. В
общем, чтобы наш код в случае ошибки не останавливался, а мы ОБРАБОТАЛИ
эту ошибку и код продолжил выполняться.

Структура try...catch...finally выглядит следующим образом:

try {
// код, который может выбросить исключение (ошибку)
} catch(error) {
// обработка ошибки
} finally {
// код, который выполнится всегда
}

В блоке try помещается код, который потенциально может вызвать ошибку, а в


блоке catch указывается код, который будет выполнен, если произойдет ошибка.
При возникновении ошибки выполнение кода в блоке try прерывается, и
управление передается блоку catch , где параметр error содержит информацию
об ошибке.
finally - это блок, который выполняется всегда после выполнения блока try и/
или catch , независимо от того, было ли выброшено исключение или нет.
Блок необязательный. Если его нет, то после выполнения блока try и/или
finally

catch управление передается дальше в программу. Если finally есть, то после


его выполнения управление также передается дальше.

Таким образом, блок finally позволяет гарантировать


выполнение некоторого кода, независимо от того, произошла

4.3. try…catch...finally 1
ошибка или нет.

Сравни 2 этих кода по выводам в консоль:

try {
const a = 10;
console.log(a+b); // тут ошибка, нет переменной b
} catch (error) {
console.log("Ошибка: " + error.message); // Ошибка: b is not defined
} finally{
console.log("сюда код дойдет");
}
console.log("и сюда код тоже дойдет");

//----- то же самое но без try...catch...finally -----

const a = 10;
console.log(a+b); // тут ошибка, нет переменной b

console.log("сюда код НЕдойдет");

error
- это объект ошибки, который содержит информацию о типе ошибки и другие
error

данные, связанные с ошибкой.

Вот пример использования try...catch :

const someFunction = (a) => a+b;

try {
const result = someFunction(2); // вызов функции, которая может вызвать ошибку
console.log(result); // если ошибки не возникло, выводим результат
} catch (error) {
console.log("Ошибка: " + error.message); // Ошибка: b is not defined
}

В этом примере мы вызываем функцию someFunction() , которая приведет к ошибке,


так как нет параметра b. Если ошибки не возникло, мы выводим результат
функции в консоль. Если же возникла ошибка, мы выводим сообщение об
ошибке в консоль.
Параметр у catch - это объект. В этом объекте есть следующие свойства:

4.3. try…catch...finally 2
Свойство message содержит текстовое описание ошибки

Свойство name содержит имя типа ошибки

Свойство stack содержит стек вызовов, который привел к ошибке

try {
// код, который может вызвать ошибку
} catch (error) {
console.log(error.message); // выводим сообщение об ошибке
console.log(error.name); // выводим имя ошибки
console.log(error.stack); // выводим стек вызовов
}

Откуда взялся этот объект error?


В JavaScript существует объект Error , который является базовым для всех
встроенных типов ошибок, таких как TypeError , RangeError , ReferenceError и др.

Кроме того, можно создавать собственные ошибки с помощью конструктора Error

и ключевого слова throw.

Если хочешь, можешь подробнее прочесть в документации


https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Error

throw
в JavaScript используется для генерации исключений (ошибок). Когда
throw throw

вызывается в коде, выполнение этого кода прекращается, и управление


передается к ближайшему обработчику исключений ( catch , finally , или
вызывающему коду).

Синтаксис оператора throw выглядит следующим образом:

throw выражение;

Здесь выражение - это объект, который представляет ошибку или исключительную


ситуацию, которую нужно сгенерировать. Это может быть любой тип данных, но
обычно это объект Error или его подкласс.

4.3. try…catch...finally 3
Вот пример использования оператора throw для генерации ошибки:

function divide(x, y) {
if (y === 0) {
throw new Error("Деление на ноль невозможно");
}
return x / y;
}

try {
const result = divide(6, 0);
} catch (error) {
console.log(error.message);
}

В этом примере функция divide принимает два аргумента и возвращает результат


деления первого на второй. Однако, если второй аргумент равен 0, функция
генерирует ошибку, используя оператор throw .

В блоке try мы вызываем функцию divide с аргументами 6 и 0, что должно


привести к генерации ошибки. Затем мы перехватываем ошибку в блоке catch и
выводим сообщение об ошибке.

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

вводе данных.
Например, так можно выбросить исключение:

function calculateAverage(grades) {
if (grades.some(grade => grade < 0)) {
throw "Оценки не могут быть отрицательными!";
}

const total = grades.reduce((sum, grade) => sum + grade, 0);


return total / grades.length;
}

try {
const result = calculateAverage([4, 5, 3, -2, 6]);

4.3. try…catch...finally 4
console.log(result);
} catch (error) {
console.error(error);
}

В этом примере, если массив grades содержит отрицательную оценку, будет


выброшено исключение с сообщением "Оценки не могут быть
отрицательными!". Мы используем конструкцию try...catch , чтобы перехватить
это исключение и вывести сообщение об ошибке в консоль.
В целом, оператор throw позволяет создавать собственные ошибки и исключения,
которые можно обрабатывать в блоках try...catch или даже внутри других
функций, если они являются частью вызова стека. Он является важной частью
обработки ошибок в JavaScript и позволяет разработчикам создавать более
надежный код.

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

2. Напиши функцию, которая принимает на вход массив чисел и возвращает


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

3. Напиши функцию, которая принимает на вход объект с полями x и y и


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

4. Напиши функцию, которая принимает на вход строку и возвращает ее длину. В


случае, если аргумент не является строкой, функция должна бросать
исключение.

5. Напиши функцию, которая принимает на вход число и возвращает его


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

Каждое задание можно усложнить, добавив дополнительные условия или


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

4.3. try…catch...finally 5
обоих аргументов, для третьего задания можно добавить проверку на тип
значений полей x и y , и т.д.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/Jo85vcDQUbpmqj1c9

🪧 4.4. Прототип

4.3. try…catch...finally 6
🪧
4.4. Прототип
Прототипы - это особенность языка JavaScript, которая позволяет создавать
объекты, унаследованные от других объектов.
Прототип является объектом-предком для другого объекта, и когда свойство или
метод не найден в самом объекте, JavaScript автоматически ищет его в
прототипе.
Это позволяет создавать более эффективный и гибкий код, так как можно
определить общие свойства и методы для группы объектов, а затем использовать
их для каждого объекта в этой группе, без необходимости повторять код для
каждого объекта.

Прототипы также позволяют расширять функциональность встроенных объектов в


JavaScript, таких как массивы и строки, добавляя новые методы и свойства (но так
лучше не делать в продакшене 🫣).
В JavaScript все объекты имеют внутреннее свойство, называемое "прототип",
которое определяет их свойства и методы.
Прототип может быть равен null , либо ссылаться на другой объект .

Представь, что у тебя есть объект-"родитель", который имеет некоторые свойства


и методы, и ты хочешь создать новый объект-"ребенок", который будет
наследовать эти свойства и методы. Для этого нужно использовать прототипы:

// Создаем объект-родитель
const parent = {
name: "Родитель",
greet: function() {
console.log("Привет, я " + this.name);
}
};

// Создаем объект-ребенок, наследуя свойства и методы от родителя


const child = Object.create(parent);
child.name = "Ребенок";
child.greet(); // "Привет, я Ребенок"

4.4. Прототип 1
В этом примере мы создали объект "родитель" с именем и методом приветствия.
Затем мы создали объект "ребенок", используя метод Object.create() , который
создает новый объект с указанным объектом в качестве прототипа. Затем мы
переопределили имя ребенка и вызвали метод приветствия, который был
унаследован от родителя.
Таким образом, прототипы позволяют нам создавать объекты, которые наследуют
свойства и методы от других объектов, что делает код более модульным и
удобным для работы.

Как задать прототип?


1. Object.create()

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


Object.create()

существующий объект в качестве прототипа. Этот метод является одним из


способов реализации наследования в JavaScript через прототипы.

Синтаксис метода Object.create() выглядит следующим образом:

Object.create(proto, propertiesObject);

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


прототипа для нового объекта. Второй аргумент propertiesObject (необязательный)
- это объект, который может содержать определения свойств и методов для нового
объекта.

2. Свойство __ proto __

- это скрытое свойство объекта в JavaScript, которое ссылается на его


__proto__

прототип. Оно представляет собой свойство-аксессор, то есть геттер и сеттер


одновременно (c помощью него значит можно как установить так и получить
свойство)
С помощью __proto__ можно получить ссылку на прототип объекта или установить
новый прототип.

4.4. Прототип 2
// Создаем объект-родитель
const parent = {
name: "Родитель",
greet: function() {
console.log("Привет, я " + this.name);
}
};

// Создаем объект-ребенок, наследуя свойства и методы от родителя


const child = {
name: "Ребенок",
__proto__: parent,
};

child.greet(); // "Привет, я Ребенок"

Кроме того, свойство __proto__ можно использовать для изменения прототипа


объекта:

const parent = {
name: "Родитель",
greet: function() {
console.log("Привет, я " + this.name);
}
};

const child = {
name: "Ребенок",
};

child.__proto__ = parent;

child.greet(); // "Привет, я Ребенок"

В этом примере мы создали объект parent и объект child , которому не был


установлен прототип. Затем мы установили parent в качестве прототипа объекта
child с помощью __proto__ . Теперь child наследует метод greet от parent .

Хотя свойство __proto__ может быть полезным для получения


ссылки на прототип объекта или установки нового прототипа,
его использование не рекомендуется в коде на продакшене,
поскольку оно не является стандартным и может быть

4.4. Прототип 3
несовместимо с некоторыми браузерами. Вместо этого
рекомендуется использовать методы Object.getPrototypeOf() и
Object.setPrototypeOf() .

Итого: есть 2 способа задать прототип при создании через Object.create() и через
свойство __ proto __ .
Есть 2 ограничения на прототипы:

1. Прототип не может быть циклическим. Если объект А наследует от объекта B,


а объект B наследует от объекта A, то это приведет к циклическому
наследованию, которое приведет к ошибке.

2. Значение __proto__ может быть объектом или null . Другие типы


игнорируются.

Цепочка прототипов
В JavaScript цепочка прототипов отображает наследование свойств и
методов между объектами. Каждый объект имеет внутреннюю ссылку на свой
прототип, который является объектом, от которого он наследует свойства и
методы.
Если свойство или метод не найден в объекте, то поиск происходит в его
прототипе, а затем в прототипе прототипа и так далее до тех пор, пока свойство
или метод не будет найден или не достигнут конец цепочки прототипов.

4.4. Прототип 4
Например, у нас есть объект "dog" с прототипом "animal" , а прототипом "animal"
является объект "livingBeing" . В этом случае цепочка прототипов выглядит
следующим образом:

dog --> animal --> livingBeing --> Object.prototype --> null

Вот пример кода, который демонстрирует цепочку прототипов:

// Прототип объекта "livingBeing"


const livingBeing = {
breathe: function() {
console.log("Дышит");
}
};

// Прототип объекта "animal"


const animal = Object.create(livingBeing);

4.4. Прототип 5
animal.eat = function() {
console.log("Ест");
};

// Объект "dog" наследует свойства и методы из прототипа "animal"


const dog = Object.create(animal);
dog.bark = function() {
console.log("Лает");
};

// Вызываем методы из цепочки прототипов


dog.bark(); // "Лает"
dog.eat(); // "Ест"
dog.breathe(); // "Дышит"

То есть когда мы обращаемся dog.breathe() JavaScript “поищет” метод breathe у


себя, не найдет, пойдет “искать” в прототип (то есть animal ) там тоже не найдет, и
дальше пойдет искать в прототипе animal (то есть livingBeing ) там найдет и
вызовет его.

Свойство prototype
В JavaScript, каждая функция является объектом, и у каждой функции есть
свойство prototype , которое представляет прототип этой функции.
Свойство prototype функции является объектом, который используется как
прототип для объектов, создаваемых с помощью этой функции при вызове
оператора new .
Этот объект содержит свойства и методы, которые будут унаследованы
экземплярами, созданными с помощью функции-конструктора.
Для лучшего понимания, давай рассмотрим следующий пример:

function Person(name, age) {


this.name = name;
this.age = age;
}

Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old`);
};

let person1 = new Person("Alice", 25);


let person2 = new Person("Bob", 30);

4.4. Прототип 6
person1.sayHello(); // выводит "Hello, my name is Alice and I'm 25 years old"
person2.sayHello(); // выводит "Hello, my name is Bob and I'm 30 years old"

Здесь мы создали функцию-конструктор Person , которая принимает два параметра


name и age . Мы также добавили метод sayHello() в свойство prototype функции
Person . Затем мы создали два экземпляра person1 и person2 , используя оператор

new и передавая в функцию-конструктор параметры name и age .

Оба экземпляра person1 и person2 наследуют свойство sayHello() от prototype

функции Person . Это означает, что мы можем вызвать метод sayHello() на обоих
объектах, и метод будет работать корректно.
С помощью prototype в уже существующие объекты можно добавлять новые
методы или создавать полифилы.

Полифил - это код, который добавляет в браузер отсутствующую


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

Array.prototype.filter = function(callback, thisArg) {


const filteredArr = [];
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) {
filteredArr.push(this[i]);
}
}
return filteredArr;
};

Функция filter принимает два аргумента: callback (функция обратного вызова,


где нужно прописать условие для фильтрации), и thisArg (необязательный
аргумент), который является значением this , используемым в callback-функции.

В цикле for перебираются элементы массива, и если функция обратного вызова


возвращает true , то элемент добавляется в новый массив filteredArr . В конце
функция filter возвращает этот новый массив.

Полезные статьи на тему:

4.4. Прототип 7
1. https://habr.com/ru/company/otus/blog/685528/

2. https://habr.com/ru/post/518360/

2. https://habr.com/ru/company/hexlet/blog/260427/

Задания
1. Создать объект с помощью функции-конструктора и добавить ему свойства и
методы через прототип.

2. Создать цепочку объектов (3 шт.) с помощью прототипов и вызвать методы из


всех объектов в цепочке.

3. Что выведет в консоль? Почему?

const obj = {
a: "AAA",
__proto__: {
a: "BBB",
funcA() {
return this.a;
}
}
}

console.log(obj.funcA());

4. Что выведет в консоль? Почему?

const obj = {
a: "AAA",
}
const obj2 = {
a: "BBB",
funcA() {
return this.a;
}
}

obj.__proto__ = obj2;

console.log(obj.funcA());

4.4. Прототип 8
5. Написать полифил для метода массива .map.

6. Написать полифил для метода массива .filter.

7. Откуда у строки взялся метод .slice ?

8. Докажи, что утверждение “в js один тип данных - объект” правдивое.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/ZtYZNcdVSJZ75Rm58

🗓 4.5. Дата и время

4.4. Прототип 9
🗓
4.5. Дата и время
В JavaScript существует встроенный объект Date, который позволяет работать с
датами и временем.

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


Создать объект Date можно несколькими способами:

1. Новый объект Date с текущей датой и временем:

const now = new Date();


console.log(now); // текущая дата и время

2. Новый объект Date с определенной датой и временем:

const date = new Date(2023, 2, 17, 12, 30, 0);


console.log(date); // Sat Mar 17 2023 12:30:00 GMT+0300 (Moscow Standard Time)

Параметры функции new Date(year, month, day, hours, minutes, seconds, ms) задают
год, месяц (от 0 до 11), день, часы, минуты, секунды и миллисекунды
(опционально). Обратите внимание, что месяцы начинаются с 0 (январь), а не с 1
(февраль).

3. Новый объект Date с помощью строки:

const date = new Date("2023-03-17T12:30:00");


console.log(date); // Sat Mar 17 2023 12:30:00 GMT+0300 (Moscow Standard Time)

Получение информации о дате и времени


Методы объекта Date позволяют получить информацию о дате и времени:

4.5. Дата и время 1


const now = new Date();

// Получить год, месяц, день, часы, минуты, секунды и миллисекунды


console.log(now.getFullYear()); // 2023
console.log(now.getMonth()); // 2 (март)
console.log(now.getDate()); // 17
console.log(now.getHours()); // текущий час
console.log(now.getMinutes()); // текущая минута
console.log(now.getSeconds()); // текущая секунда
console.log(now.getMilliseconds()); // текущая миллисекунда

// Получить день недели (от 0 до 6, где 0 - воскресенье, 6 - суббота)


console.log(now.getDay()); // 5 (пятница)

Форматирование даты и времени


Методы объекта Date также позволяют форматировать дату и время:

const now = new Date();

// Форматирование даты в формате "ДД.ММ.ГГГГ"


const formattedDate = `${now.getDate()}.${now.getMonth() + 1}.${now.getFullYear()}`;
console.log(formattedDate); // 17.3.2023

// Форматирование времени в формате "ЧЧ:ММ:СС"


const formattedTime = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
console.log(formattedTime); // текущее время в формате "ЧЧ:ММ:СС"

Вот все что ты сейчас прочел надо знать, но для работы с датами и временем в
React/Redux , Node.js и т.д. используется библиотека moment.js

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

Задания
1. Напиши функцию, которая будет принимать на вход дату и время и
возвращать ближайшее время в формате "ЧЧ:ММ", кратное 5 минутам.
Например, если на вход подано "17.03.2023 12:13", то функция должна вернуть
"12:10".

4.5. Дата и время 2


2. Напиши функцию, которая будет принимать на вход две даты и возвращать
разницу между ними в днях.

3. Напиши функцию, которая будет принимать на вход дату в формате "ММ/ДД/


ГГГГ" или "ГГГГ/ММ/ДД" и возвращать ее представление в формате
"ДД.ММ.ГГГГ".

4. Напиши функцию, которая будет принимать на вход дату и время и


возвращать строку, содержащую информацию о том, сколько времени прошло
с момента заданной даты до текущего момента. Например, "2 дня назад", "3
часа назад", "10 минут назад" и т.д.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/MPGztwFUcHKMRyfu8

💥 4.6. Коллекции. Map и Set

4.5. Дата и время 3


💥
4.6. Коллекции. Map и Set
Коллекция (Collection) - это общее название для различных типов объектов,
которые хранят наборы значений. В JavaScript существует несколько типов
коллекций, каждый из которых предназначен для определенных задач.
Мы уже знаем:

объект - неупорядоченная коллекция свойств (пара ключ:значение )

массив - упорядоченная коллекция значений

и вот дальше я предлагаю вам ознакомиться с еще двумя коллекциями…

Map
Map — это коллекция, которая хранит данные в виде пар ключ-значение. При этом
ключ может быть любого типа (включая объекты и функции), а значение — любого
типа данных (примитивы, объекты и функции). Map сохраняет порядок добавления
элементов, и предоставляет методы для добавления, удаления и получения
элементов по ключу.
new Map() – создаёт коллекцию.

map.set(key, value) – записывает по ключу key значение value.


map.get(key) – возвращает значение по ключу или undefined, если ключ key
отсутствует.

map.has(key) – возвращает true, если ключ key присутствует в коллекции, иначе


false.
map.delete(key) – удаляет элемент по ключу key.
map.clear() – очищает коллекцию от всех элементов.
map.size – возвращает текущее количество элементов.

Пример использования Map:

4.6. Коллекции. Map и Set 1


const map = new Map();

// добавляем элементы в Map


map.set('key1', 'value1');
map.set('key2', 'value2');
map.set(3, [1, 2, 3]);

// получаем элементы из Map


console.log(map.get('key1')); // 'value1'
console.log(map.get(3)); // [1, 2, 3]

// удаляем элемент из Map


map.delete('key2');

// проверяем наличие элемента в Map


console.log(map.has('key2')); // false

// перебираем элементы Map


map.forEach((value, key) => {
console.log(`${key}: ${value}`);
});

// выводим количество элементов Map


console.log(map.size); // 2

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

– создаёт Set, и если в качестве аргумента был предоставлен


new Set(iterable)

итерируемый объект (обычно это массив), то копирует его значения в новый Set.

– добавляет значение (если оно уже есть, то ничего не делает),


set.add(value)

возвращает тот же объект set.


– удаляет значение, возвращает true если value было в
set.delete(value)

множестве на момент вызова, иначе false.

set.has(value) – возвращает true, если значение присутствует в множестве, иначе


false.
set.clear() – удаляет все имеющиеся значения.

4.6. Коллекции. Map и Set 2


set.size – возвращает количество элементов в множестве.

Пример использования Set:

const set = new Set();

// добавляем элементы в Set


set.add(1);
set.add('hello');
set.add({ name: 'John', age: 30 });

// проверяем наличие элемента в Set


console.log(set.has(1)); // true

// удаляем элемент из Set


set.delete('hello');

// перебираем элементы Set


set.forEach((value) => {
console.log(value);
});

// выводим количество элементов Set


console.log(set.size); // 2

Конечно это не все коллекции. В JS есть еще коллекции, но я не считаю что про
них нужно знать… но если вдруг ты хочешь, то вот ссылка
https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Keyed_collections

Задания
1. Напиши функцию countWords(str) , которая принимает на вход строку и
возвращает объект Map, в котором ключами являются слова из строки, а
значениями - количество их вхождений в строку.
Например, для строки "Я люблю маму, а так же я люблю JavaScript" функция должна
вернуть Map со следующими парами ключ-значение: "Я" -> 2 , "люблю" -> 2 ,
"маму" -> 1 , и т.д.

2. Напиши функцию, которая принимает на вход массив и возвращает новый


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

4.6. Коллекции. Map и Set 3


Помоги сделать эту эту главу лучше! Дай обратную связь, а мы
прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/WiVVv6UKw2bfFAua7

➿ 4.7. Замыкание. Рекурсия. Каррирование

4.6. Коллекции. Map и Set 4



4.7. Замыкание. Рекурсия.
Каррирование
Эти темы тебе нужны для собеседования! Их по сути нужно понять заучить. Их
спрашивают. Подтверждено студентами

Замыкание
Замыкание (closure) в JavaScript - это функция, которая запоминает переменные
из внешней области видимости (lexical environment), где она была объявлена,
даже после того, как эта область видимости закончила свою работу. Замыкание
формируется при объявлении функции внутри другой функции и
использовании внешних переменных внутри вложенной функции.

Проще говоря, замыкание позволяет функции "запоминать" значения переменных,


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

Простейшим примером замыкания может быть функция, которая возвращает


другую функцию, которая использует переменную, объявленную во внешней
функции:

function outer() {
let x = 10;

function inner() {
console.log(x);
}

return inner;
}

let closureFunc = outer();


closureFunc(); // 10

4.7. Замыкание. Рекурсия. Каррирование 1


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

Рассмотрим еще пример:

function createCounter() {
let count = 0;

return function() {
count++;
console.log(count);
}
}

let counter1 = createCounter();


counter1(); // 1
counter1(); // 2

let counter2 = createCounter();


counter2(); // 1
counter2(); // 2

В данном примере функция createCounter возвращает внутреннюю функцию ,


которая имеет доступ к переменной count , объявленной внутри функции
createCounter .
При вызове createCounter() создается новая область видимости со своей
переменной count . При вызове counter1() возвращенной из createCounter()
функции происходит инкремент переменной count и её вывод в консоль. Таким
образом, каждый вызов результата createCounter() увеличивает значение
переменной count , сохраненное в замыкании.

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

4.7. Замыкание. Рекурсия. Каррирование 2


определенных задач.

Вот пример простой функции, которая использует рекурсию:

function countdown(n) {
console.log(n);
if (n > 0) {
countdown(n - 1);
}
}

countdown(5);

Эта функция выводит числа от n до 0 . Когда функция вызывается с числом,


большим чем 0 , она выводит это число и вызывает себя же с аргументом n - 1 .
Это происходит до тех пор, пока аргумент не достигнет 0 , и рекурсивные вызовы
прекратятся.

Вот еще один пример - функция factorial , которая вычисляет факториал числа:

function factorial(n) {
if (n === 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}

Эта функция определяет факториал числа n как n умноженное на факториал (n-


1) . Рекурсивный вызов функции прекратится, когда аргумент n достигнет 0 , что

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

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

4.7. Замыкание. Рекурсия. Каррирование 3


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

Вот пример функции, которая складывает два числа:

function add(x, y) {
return x + y;
}

Мы можем сконвертировать ее в каррированную версию следующим образом:

function add(x) {
return function(y) {
return x + y;
}
}

Но каррирование, это не ”изменение самой функции”, поэтому правильней будет


сделать так:

function add(x, y) {
return x + y;
}

const curryAdd = (fn) => {


return function (x) {
return function (y) {
return fn(x, y)
}
}
}

console.log(curryAdd(add)(2)(3));

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


которую нужно каррировать.

Таким образом, каррирование позволяет создавать более гибкие функции,


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

4.7. Замыкание. Рекурсия. Каррирование 4


Еще один пример каррирования 🫣 Попробуй разобраться в нем.
const multiply = (a, b, c) => a * b * c;

const curry = (fn, ...args) => {


return (...newArgs) => {
const allArgs = [...args, ...newArgs];
if (allArgs.length >= fn.length) {
return fn(...allArgs);
} else {
return curry(fn, ...allArgs);
}
};
};

const curriedMultiply = curry(multiply);

console.log(curriedMultiply(2, 3, 4)); // 24
console.log(curriedMultiply(2)(3, 4)); // 24
console.log(curriedMultiply(2)(3)(4)); // 24

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

2. Задание на рекурсию: Напиши рекурсивную функцию, которая принимает на


вход массив чисел и возвращает сумму всех элементов в этом массиве.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/AZhxuujeQ4XUZQa98

🏛 5.1. class

4.7. Замыкание. Рекурсия. Каррирование 5


🏛
5.1. class
Чтобы начать главу про классы в JavaScript, полезно сначала понимать, что
классы в JavaScript появились в ECMAScript 6 (ES6) и являются новым
синтаксическим сахаром для объектно-ориентированного программирования
(ООП) в JavaScript.

Как объявить класс?


Для объявления класса в JavaScript используется ключевое слово class .
Основные блоки, которые могут быть определены в классе, включают в себя
конструктор и методы.

Вот пример объявления класса "Person" :

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

sayHello() {
console.log(`Привет, меня зовут ${this.name} и мне ${this.age} лет.`);
}
}

Здесь мы определяем класс "Person" с помощью ключевого слова class . Внутри


класса мы определяем конструктор constructor , который инициализирует
свойства объекта, и метод sayHello , который выводит сообщение в консоль.

Конструктор класса ( constructor ) определяет свойства объекта и инициализирует


их при создании нового объекта с помощью ключевого слова new .

const person = new Person("Pavel", 25);

console.log(person); // { name: 'Pavel', age: 25 }

5.1. class 1
Почему если вывести в консоль person из примера выше, то мы не увидим
там методов?
Если мы выведем объект person из примера выше в консоль, то мы действительно
не увидим там методов. Это потому, что методы в JavaScript-классах хранятся в
прототипе объекта, а не в самом объекте.
При создании объекта person на основе класса Person с помощью оператора new ,
в памяти выделяется объект, который содержит все его свойства ( name и age ). Но
метод sayHello , не хранится непосредственно в этом объекте. Вместо этого он
хранится в прототипе объекта.

Для чего нужен constructor?


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

Конструктор может принимать параметры, которые передаются при создании


объекта, и использовать их для инициализации свойств объекта. Например, если у
нас есть класс Person , который имеет свойства name и age , мы можем определить
конструктор для этого класса, который принимает значения name и age и
устанавливает их в свойства объекта:

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

При создании нового объекта на основе класса Person с помощью оператора new ,
конструктор вызывается автоматически:

const person = new Person('John', 30);

5.1. class 2
Здесь мы создаем новый объект person на основе класса Person и передаем
значения name и age в конструктор класса. Конструктор класса инициализирует
свойства объекта person , устанавливая значение name в 'John' и age в 30 .

Таким образом, конструктор класса играет важную роль в инициализации


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

Геттеры и сеттеры
Геттеры и сеттеры в классах — это специальные методы, которые позволяют
получать (get) и устанавливать (set) значения свойств объекта.

Геттеры и сеттеры обычно используются для контроля доступа к свойствам


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

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

get age() {
return this._age;
}

set age(value) {
if (value < 0) {
console.log("Возраст не может быть отрицательным");
return;
}
this._age = value;
}
}

Здесь мы определяем геттер age , который возвращает значение свойства _age ,и


сеттер age , который проверяет, что значение value не отрицательное, и
устанавливает значение свойства _age .

При использовании геттера и сеттера для свойства age , мы можем получать и


устанавливать значение свойства как обычно:

5.1. class 3
const person = new Person("Pavel", 25);

console.log(person.age); // 25

person.age = 30;
console.log(person.age); // 30

person.age = -10; // Возраст не может быть отрицательным


console.log(person.age); // 30 (значение свойства не изменилось из-за некорректного значен
ия)

Таким образом, геттеры и сеттеры могут помочь в обеспечении контроля


доступа к свойствам объекта.

Защищенные. Статические. Приватные


1. Защищенные
В JavaScript защищенные свойства - это свойства объекта, к которым можно
получить доступ только из методов класса (геттеров и сеттеров) или его
наследников.

Обычно, в классе защищенные свойства начинаются с символа подчеркивания _ .


Например:

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

get age() {
return this._age;
}

set age(value) {
if (value < 0) {
console.log("Возраст не может быть отрицательным");
return;
}
this._age = value;
}
}

5.1. class 4
Использование защищенных свойств позволяет скрыть детали реализации класса
и обеспечить его безопасность.
Защищенного свойства на самом деле не существует в стандарте языка. Это
просто договоренность между разработчиками, что свойство с нижним
подчеркиванием мы не будем менять на прямую, а будем использовать геттер и
сеттер.

2. Статические
Статические свойства и методы в JavaScript-классах — это свойства и методы,
которые принадлежат самому классу, а не его экземплярам.

Статические свойства и методы объявляются с использованием ключевого слова


static .

К статическим свойствам и методам можно обращаться как к свойствам и


методам класса, а не экземпляров класса. Например, если у нас есть класс
Person с статическим свойством count , которое содержит количество экземпляров

класса Person , мы можем обратиться к этому свойству как Person.count :

class Person {
static count = 0;

constructor(name, age) {
this.name = name;
this.age = age;
Person.count++;
}
}

const vlad = new Person("Vlad", 23);


const pavel = new Person("Pavel", 25);

console.log(Person.count); // 2

Здесь мы определяем статическое свойство count в классе Person и


инкрементируем его каждый раз при создании нового экземпляра класса. Затем
мы можем обратиться к статическому свойству count как к свойству класса Person ,
чтобы получить общее количество экземпляров класса, созданных в нашей
программе.

5.1. class 5
Пример статических методов в JS. Math.max() , Math.min() , Promise.all() ,
Promise.resolve() ,…

3. Приватные
Свойства, которые начинаются с символа # в JavaScript называются приватными
свойствами (private fields). Они были добавлены в стандарт ECMAScript 2019 и
позволяют определять свойства, которые могут быть доступны только внутри
класса (обращаются к ним через this), где они были определены.

Приватные свойства не могут быть прочитаны или изменены извне класса


Вот пример определения класса с приватным свойством:

class Person {
#name;

constructor(name) {
this.#name = name;
}

getName() {
return this.#name;
}

setName(name) {
this.#name = name;
}
}

const person = new Person("Pavel");

console.log(person.getName()); // "Pavel"

person.setName("Alina");

console.log(person.getName()); // "Alina"

console.log(person.#name); // SyntaxError: Private field '#name' must be declared in an en


closing class

В этом примере мы определили класс Person с приватным свойством #name .


Методы getName и setName используются для чтения и записи значения приватного
свойства соответственно. Обрати внимание, что попытка обратиться к приватному
свойству #name извне класса приведет к ошибке SyntaxError .

5.1. class 6
Итого:

Защищенные - это договоренность и нужны для get и set.

Статические - можем “достучаться” через класс, а не экземпляр класса


(объект).

Приватные - для использования только внутри класса, и “достучаться” к ним


мы можем только через this.

Наследование классов
В JavaScript классы наследуются с помощью ключевого слова extends при
определении дочернего класса. Класс-потомок наследует свойства и методы
родительского класса, и может добавлять собственные свойства и методы.

Вот пример определения родительского класса Person и дочернего класса


Employee , который наследует свойства и методы родительского класса:

class Person {
constructor(name) {
this.name = name;
}

sayHello() {
console.log(`Привет, меня зовут ${this.name}`);
}
}

class Employee extends Person {


constructor(name, title) {
super(name);
this.title = title;
}

introduce() {
console.log(`Привет, меня зовут ${this.name} и я ${this.title}`);
}
}

const john = new Employee("Pavel", "Developer");

john.sayHello(); // "Привет, меня зовут Pavel"


john.introduce(); // "Привет, меня зовут Pavel и я Developer"

5.1. class 7
В этом примере мы определили родительский класс Person , который имеет
свойство name и метод sayHello .
Затем мы определили дочерний класс Employee , который наследует свойства и
методы родительского класса с помощью ключевого слова extends и метода
super() .

Класс Employee также имеет свойство title и метод introduce , который выводит
информацию о себе и родительском классе. Создав экземпляр класса Employee ,
мы можем использовать как методы родительского класса Person , так и методы
дочернего класса Employee .

Что будет если не вызвать super??


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

class Person {
constructor(name) {
this.name = name;
}
}

class Employee extends Person {


constructor(title) {
this.title = title;
}
}

const john = new Employee("Developer"); // ошибка

В этом примере будет ошибка. Почему? Потому что в дочернем конструкторе нет
this , и код this.title = title; не отработает.

super
В JavaScript ключевое слово super используется внутри конструктора дочернего
класса для вызова конструктора родительского класса и получения доступа к его
свойствам и методам.
То есть, когда мы вызывали в примере выше super(name) у класса Employee мы
вызывали constructor класса Person . Вот и всë.

Вызываешь у дочернего super() - вызывается constructor родителя.

5.1. class 8
Так же super можно использовать для вызова метода

class Person {
sayHi() {
return "Hi"
}
}

class Employee extends Person {


introduce() {
console.log(`Привет, ${super.sayHi()}`);
}
}

const person = new Employee();

person.introduce(); // "Привет, Hi"

Тут мы с помощью super вызвали родительский метод sayHi в методе дочернего


класса.

Вывод:

1) чтобы вызвать родительский метод в дочернем классе, нужно использовать


super!

2) чтобы вызвать конструктор родителя

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

Синтаксис переопределения методов класса:

class Animal {
makeSound() {
console.log("Animal is making a sound");
}
}

class Dog extends Animal {


makeSound() {

5.1. class 9
console.log("Woof woof!");
}
}

const dog = new Dog();


dog.makeSound(); // "Woof woof!"

В этом примере, класс Dog наследует метод makeSound от класса Animal . Однако, в
классе Dog переопределен метод makeSound , который выводит на консоль строку
"Woof woof!" вместо того, что выводит метод makeSound класса Animal .
При вызове метода makeSound на экземпляре класса Dog , будет вызван
переопределенный метод makeSound , который выводит строку "Woof woof!".
Если в переопределенном методе нужно вызвать унаследованный метод, можно
использовать ключевое слово super .

Пример использования super :

class Animal {
makeSound() {
console.log("Animal is making a sound");
}
}

class Dog extends Animal {


makeSound() {
super.makeSound();
console.log("Woof woof!");
}
}

const dog = new Dog();


dog.makeSound(); // "Animal is making a sound" "Woof woof!"

В этом примере, переопределенный метод makeSound класса Dog вызывает метод


makeSound класса Animal с помощью super.makeSound() , а затем выводит строку "Woof

woof!". При вызове метода makeSound на экземпляре класса Dog , будет вызван
переопределенный метод makeSound , который выводит строки "Animal is making a
sound" и "Woof woof!".

instanceof

5.1. class 10
- это оператор в JavaScript, который используется для проверки,
instanceof

является ли объект экземпляром определенного класса. Он возвращает значение


, если объект является экземпляром указанного класса, и
true false , если он не
является.

Синтаксис оператора instanceof :

object instanceof class

object - объект, который нужно проверить.

class - класс, который нужно проверить.

Пример использования оператора instanceof :

class Animal {}

class Dog extends Animal {}

class Car {}

const dog = new Dog();

console.log(dog instanceof Dog); // true


console.log(dog instanceof Car); // false
console.log(dog instanceof Animal); // true
console.log(dog instanceof Object); // true

В этом примере, класс Dog наследуется от класса Animal . Создается экземпляр


класса Dog с помощью оператора new . Затем проверяется, является ли объект
dog экземпляром класса Dog , Animal и Object . Все проверки возвращают true ,

потому что объект dog является экземпляром всех этих классов.

Оператор instanceof проверяет не только прямое наследование, но и косвенное.


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

5.1. class 11
Примеси (mixins)
Начнем с того, что в JavaScript не существует множественного наследования. То
есть мы не можем наследовать класс от нескольких классов.

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

Примеси могут быть определены как отдельные объекты, содержащие методы и


свойства, которые могут быть добавлены к любому классу. Для этого используется
ключевое слово mixins . Например:

const myMixin = {
mixinMethod() {
console.log('Этот метод из миксина');
}
};

class MyClass {
// ...
}

Object.assign(MyClass.prototype, myMixin);

const obj = new MyClass();


obj.mixinMethod(); // 'Этот метод из миксина'

Здесь мы создаем объект myMixin , содержащий метод mixinMethod . Затем мы


добавляем этот метод в прототип класса MyClass с помощью метода
Object.assign() .

ОБРАЩАЮ ВНИМАНИЕ ЧТО ИМЕННО В ПРОТОТИП мы “ПОДМЕШИВАЕМ”


метод.

После этого мы можем создать экземпляр класса MyClass и вызвать добавленный


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

5.1. class 12
внимательно выбирать имена методов, а также контролировать их использование
в коде.

Еще материал по теме:


1. https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes

Задания
1. Создай класс Rectangle с двумя свойствами: width и height . Добавь метод
getArea() , который будет возвращать площадь прямоугольника.

2. Создай класс Square , который наследует свойства и методы класса Rectangle и


имеет дополнительное свойство sideLength . Переопредели метод getArea() так,
чтобы он возвращал площадь квадрата.

3. Создай класс Teacher с одним свойством name и методом gradeStudent(student,


grade) , который будет добавлять оценку grade в массив оценок студента

student .

4. Создай класс BankAccount с двумя свойствами: balance и ownerName . Добавь


методы deposit(amount) и withdraw(amount) , которые будут добавлять и снимать
сумму amount со счета соответственно. Добавь метод getBalance() , который
будет возвращать текущий баланс счета.

5. Создай класс Product с двумя свойствами: name и price . Добавь метод


priceWithTax , который будет возвращать цену товара с учетом налога на

продажи в размере 10%. Процентную ставку нужно хранить в приватном


свойстве.

Дополнительное задание для монстров программирования!


Задача описать класс Student по тз ниже;

1. Написать валидацию для каждого свойства.

name. Только латиница. Не меньше 2-х символов и не больше 15-ти


включительно;

age. Только цифры. От 18 до 65 включительно;

5.1. class 13
isMan. Boolean. true || false;

createdDate. Дата создания студента. Формат(dd/mm/yyyy);

2. Информацию по допустимому возрасту и доступным полам хранить в


приватных свойствах.
#validAge = {min: 18, max:65}

3. Написать метод showInfo, который вернет всю информацию экземпляра


класса.
(имя, возраст, пол в виде male||female, дату создания в формате (dd-mm-
yyyy))

4. Для обработки ошибок создать класс MyCustomError.


В случае возникновения ошибки, сгенерировать ошибку и вывести еe
сообщение;
Для обработки ошибок, нужно создать свой собственный класс MyCustomError.
Например, если возникла ошибка при валидации имени, нужно сгенерировать
ошибку на основе своего класса и вывести например в консоль.
Ошибку пробрасываем через try...catch.

5. Исходные данные для создания студентов хранить в JSON (минимум 5


студентов из них 3 не валидных). То есть к примеру массив объектов.

const JSON = "[{name: 'pasha',...},{}, {}]";

6. По необходимости использовать деструктуризацию и оператор spread, где это


необходимо.

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/7kG4ZznWkB1VgQqKA

🪧 5.2. ООП в JavaScript


5.1. class 14
🪧
5.2. ООП в JavaScript
ООП (объектно-ориентированное программирование) - это парадигма
программирования, которая основывается на идее, что данные должны быть
связаны в единицы называемые объектами. Есть 4 основных концепции ООП:

1. Наследование - принятие свойств и методов одного класса другим.

2. Инкапсуляция - сокрытие деталей реализации от пользователя.

3. Полиморфизм - способность объектов разных типов отвечать на один и тот


же метод.

4. Абстракция - выделение общих свойств и методов схожих объектов.

Сейчас расскажу подробнее про каждый, но для начала вспомним


Объект - это экземпляр класса (инстанс), который содержит свойства и методы.

Класс - это шаблон для создания объектов.

Наследование
Наследование в JavaScript - это механизм, который позволяет одному классу
(дочернему) наследовать свойства и методы другого класса (родителя).
Пример наследования в JavaScript

class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} шумит.`);
}
}

class Dog extends Animal {


speak() {
console.log(`${this.name} лает.`);
}

5.2. ООП в JavaScript 1


}

const myAnimal = new Dog("Jack");


myAnimals.speak(); // "Jack лает."

В данном примере класс Dog наследует все свойства и методы класса Animal и
может их использовать и переопределять.
Но надо помнить, что “под капотом” JavaScript использует прототипное
наследование. Это означает, что объекты наследуют свойства и методы от своего
прототипа, который является другим объектом.

Инкапсуляция
Инкапсуляция - это механизм ООП, который ограничивает доступ к свойствам и
методам класса снаружи.
Пример инкапсуляции в JavaScript
В этом примере я использую _balance как закрытое свойство класса, и мы можем
использовать методы get и set для доступа к нему.

class BankAccount {
constructor(balance) {
this._balance = balance;
}

get balance() {
return this._balance;
}

set balance(amount) {
if (amount < 0) {
console.log("Невозможно установить отрицательный баланс");
return;
}
this._balance = amount;
}

deposit(amount) {
this.balance += amount;
}

withdraw(amount) {
if (this.balance - amount < 0) {
console.log("Недостаточно средств");
return;
}

5.2. ООП в JavaScript 2


this.balance -= amount;
}
}

const account = new BankAccount(100);


console.log(account.balance); // 100
account.balance = -50; // Невозможно установить отрицательный баланс
console.log(account.balance); // 100
account.deposit(50);
console.log(account.balance); // 150
account.withdraw(200); // Недостаточно средств
console.log(account.balance); // 150

Полиморфизм
Полиморфизм в JavaScript - это возможность использовать один и тот же метод
для различных инстансов класса (объектов).

Пример полиморфизма в JavaScript

class Shape {
draw() {
console.log("Рисуем фигуру");
}
}

class Circle extends Shape {


draw() {
console.log("Рисуем круг");
}
}

class Square extends Shape {


draw() {
console.log("Рисуем квадрат");
}
}

const shape = new Shape();


const circle = new Circle();
const square = new Square();

shape.draw(); // "Рисуем фигуру"


circle.draw(); // "Рисуем круг"
square.draw(); // "Рисуем квадрат"

5.2. ООП в JavaScript 3


В этом примере, класс Shape определяет метод draw() который может быть
переопределен в классах-наследниках Circle и Square . Мы можем создавать
экземпляры различных классов и вызывать метод draw() для каждого, но получим
различный результат. Это показывает полиморфизм в действии.

Абстракция
Абстракция в JavaScript означает создание структуры свойств и методов,
которые могут быть использованы для представления конкретного объекта или
категории объектов. Посмотри вокруг. Тебя окружают объекты!! Реализуешь их в
JS - это и будет абстракцией.
Пример абстракции в JavaScript

class Car {
constructor(make, model) {
this.make = make;
this.model = model;
}
honk() {
console.log('Бип-бип!');
}
}

const myCar = new Car('BMW', 'X5');


console.log(myCar.make); // 'BMW'
console.log(myCar.model); // 'X5'
myCar.honk(); // 'Бип-бип!'

В данном примере класс Car является абстракцией для объекта автомобиля,


который имеет свойства make и model, и метод honk. Объект myCar создается с
помощью класса Car и инициализирует свойства make и model.

P.S Если тебе стало понятнее и понравились примеры, отправь мне в личку

🔄 6.1. Асинхронный код

5.2. ООП в JavaScript 4


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

Основной цикл выполнения кода в JavaScript называется "Event Loop" (цикл


событий). Когда JavaScript исполняет код, он добавляет события в очередь
событий. Эти события обрабатываются по мере их поступления, начиная с самого
раннего. (про все это поговорим дальше в теме Event Loop)
JavaScript выполняется последовательно и блокирует выполнение других
задач до тех пор, пока текущая задача не будет выполнена. Однако, как я уже
упоминал, JavaScript также поддерживает асинхронное выполнение, которое
позволяет продолжать выполнение кода, не ожидая завершения других операций.

Асинхронный код - это способ написания кода, который не блокирует


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

Асинхронный код же позволяет продолжать выполнение программы без


ожидания завершения операции. Вместо этого, код запускает операцию и
передает ее выполнение в фоновый поток. Когда операция завершится, код
получит уведомление о ее результате и продолжит свою работу.
В JavaScript асинхронный код реализуется с помощью колбэков, промисов и
асинхронных функций.
Я приведу несколько ПРОСТЫХ примеров кода на JavaScript, чтобы показать
разницу между синхронным и асинхронным кодом.

6.1. Асинхронный код 1


Пример 1: Синхронный код

function syncCode() {
console.log("начало");
console.log("первый");
console.log("второй");
console.log("конец");
}

syncCode();

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

Пример 2: Асинхронный код

function asyncCode() {
console.log("начало");
setTimeout(() => {
console.log("первый");
}, 2000);
setTimeout(() => {
console.log("второй");
}, 1000);
console.log("конец");
}

asyncCode();

Этот код выполнится асинхронно, и выведет в консоль сначала "начало", затем


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

setTimeout
- это функция, которая позволяет задать отсрочку выполнения
setTimeout

определенного кода. Она принимает два аргумента: функцию, которую нужно


выполнить, и время задержки в миллисекундах.
Синтаксис функции setTimeout :

6.1. Асинхронный код 2


setTimeout(function, delay);

- функция, которую нужно выполнить после задержки. Может быть


function

определена как анонимная функция или ссылка на функцию.

- время задержки в миллисекундах, после которого нужно выполнить


delay

функцию. Значение может быть целым числом или дробным числом.

Пример использования setTimeout :

function sayHello() {
console.log("Привет, мир!");
}

// Вызов функции sayHello через 1 секунду


setTimeout(sayHello, 1000);

В этом примере, функция sayHello будет вызвана через 1 секунду после


выполнения setTimeout .

Также, setTimeout возвращает уникальный идентификатор таймера, который


можно использовать для отмены выполнения функции с помощью clearTimeout .

Пример отмены выполнения setTimeout :

const timerId = setTimeout(() => {


console.log("Этот код не выполнится");
}, 1000);

clearTimeout(timerId); // Отмена выполнения setTimeout

В этом примере, setTimeout запускает анонимную функцию через 1 секунду, а


затем функция clearTimeout отменяет выполнение setTimeout с помощью передачи
уникального идентификатора timerId .
Полезные статьи на HABR:

1) https://habr.com/ru/post/651037/
2) https://habr.com/ru/post/439620/

6.1. Асинхронный код 3


🔙
6.2. callback
Callback-функции - это функции, которые передаются в качестве аргументов в
другие функции и вызываются после выполнения определенных действий.

function sayName(){
return "Pavel";
}

function sayHi(callback){
console.log(`Hi, ${callback()}`)
}

sayHi(sayName);

В этом примере callback-функцией является функция sayName . Ее мы передаем в


аргументы другой функции и вызываем в ней.

Эта концепция является важной частью асинхронного программирования в


JavaScript.

Колбэки могут быть использованы во многих сценариях, например:

Обработка событий: callback-функция может быть передана в обработчик


событий, который будет вызван при возникновении события, такого как щелчок
мыши или отправка формы. (дальше ты с этим познакомишься)

Загрузка данных: callback-функция может быть передана в функцию, которая


загружает данные из удаленного источника, и вызвана после завершения
загрузки.

Анимация: callback-функция может быть передана в функцию, которая


выполняет анимацию, и вызвана после завершения анимации.

Еще пример:

6.2. callback 1
function someFunction(arg1, arg2, callback) {
const result = arg1 + arg2;
callback(result);
}

function myCallback(result) {
console.log('Результат: ' + result);
}

someFunction(2, 3, myCallback);

Callback hell
Callback hell - это ситуация, когда вложенные асинхронные функции вызывают
друг друга с использованием обратных вызовов, что приводит к громоздкому и
сложному для понимания коду. Код становится сложнее поддерживать,
отлаживать и масштабировать. Примеры таких ситуаций могут включать
последовательные запросы к API или обработку больших объемов данных.

Вот пример кода на JavaScript, демонстрирующий проблему callback hell:

function getData(callback) {
someAsyncFunction(function(result) {
anotherAsyncFunction(result, function(newResult) {
yetAnotherAsyncFunction(newResult, function(finalResult) {
callback(finalResult);
});
});
});
}

Код использует три асинхронные функции, каждая из которых использует


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

Вот пример, как можно исправить эту проблему с использованием промисов:

function getData() {
return someAsyncFunction()
.then(result => anotherAsyncFunction(result))

6.2. callback 2
.then(newResult => yetAnotherAsyncFunction(newResult))
}

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

В заключение, callback hell - это проблема, которую можно решить с помощью


использования альтернативных методов, таких как промисы или async/await. Они
делают код более линейным и понятным, что облегчает его поддержку и
масштабирование.

Про них поговорим дальше…

Задания
1. Напиши функцию sumNumbers, которая принимает два числа a и b и callback-
функцию. Функция должна сложить числа a и b и передать результат в
callback-функцию которая выведет результат в консоль.

2. Напиши функцию, которая принимает массив и callback-функцию, а затем


проходит по каждому элементу массива и вызывает переданную callback-
функцию для каждого элемента. Callback-функция должна принимать один
аргумент - текущий элемент массива - и выводить его в консоль.

3. Напиши функцию, которая принимает массив строк и callback-функцию, а


затем вызывает переданную callback-функцию для каждой строки в массиве.
Сallback-функция должна преобразовывать строку в верхний регистр и
выводить ее в консоль.

4. Напиши функцию, которая принимает массив чисел и callback-функцию, а


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

5. Напиши функцию, которая принимает массив объектов и callback-функцию, а


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

6.2. callback 3
Помоги сделать эту эту главу лучше! Дай обратную связь, а мы
прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/GjKWUxTxWKqQJqVM7

6.3. Promise

6.2. callback 4
6.3. Promise
Промис (Promise) - это объект в JavaScript, который представляет собой
неопределенное значение, которое будет вычислено в будущем. Промисы
используются для работы с асинхронным кодом, который выполняется не сразу, а
после выполнения какой-то операции, которая может занять время. Например,
загрузка данных с сервера.

Промисы облегчают написание асинхронного кода, упрощая управление


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

6.3. Promise 1
(callback hell), при использовании промисов можно использовать цепочку
методов, что делает код более читабельным и легко поддерживаемым.

Вот тебе пример промиса:

const promise = new Promise((resolve, reject) => {


setTimeout(() => {
resolve("Привет, Redev!");
}, 2000);
});

promise
.then((result) => {
console.log(result); // "Привет, Redev!"
})
.catch((error) => {
console.error(error);
});

В этом примере создается промис, который через 2 секунды возвращает значение


"Привет, Redev!" . Затем результат обрабатывается с помощью метода .then() . Если

происходит ошибка, она обрабатывается с помощью метода .catch() .

Теперь подробнее про него поговорим.

Что такое resolve, reject?


и reject - это callback-функции, которые используются для изменения
resolve

состояния промиса на "выполнено" (resolve) или "отклонено" (reject).

Что такое состояние промиса? (state)


У объекта promise , возвращаемого конструктором new Promise , есть внутренние
свойства state и result.

{
state: "pending" || "fulfilled" || "rejected",
result: undefined || value || error
}

Промисы могут находиться в одном из трех состояний (state):

6.3. Promise 2
ожидание (pending)

выполнено (fulfilled)

отклонено (rejected).

Свойство result вслед за статусами имеет 3 значения — вначале undefined , далее


изменяется на value при вызове resolve(value) или на error при вызове
reject(error) .

Когда промис в состоянии ожидания, он выполняет асинхронную операцию. Когда


операция завершается успешно, промис переходит в состояние выполнено и
возвращает результат, который можно обработать с помощью метода .then() .
Если операция не выполняется успешно, промис переходит в состояние
отклонено и возвращает ошибку, которую можно обработать с помощью метода
.catch() .

!!! СЮДА СХЕМА СО СТАТУСАМИ !!!

То есть зафиксируем:

Промис - это объект. У этого объекта есть свойства state и result и методы
.then() и .catch() . Создается промис с помощью конструктора new Promise() . У

этого конструктора есть один параметр - функция, которая называется


исполнитель (executor). Исполнитель принимает два аргумента - resolve и reject,
которые являются callback-функциями и используются для разрешения (resolve)
или отклонения (reject) промиса.

Подробнее про методы-обработчики


Методы-обработчики .then() и .catch() являются основными методами, которые
используются для обработки результатов выполнения промисов.

.then()
Метод then() вызывается, когда промис переходит в состояние выполнено, т.е.
когда асинхронная операция завершается успешно.

6.3. Promise 3
Этот метод принимает две callback-функции - одну для обработки успешно
разрешенного промиса (fulfilled), а другую для обработки отклоненного промиса
(rejected).

promise.then(onFulfilled, onRejected)

promise.then(
(result) => console.log(result), // сработает в случае resolve
(error) => console.log(error) // сработает в случае reject
);

где:

onFulfilled (опциональный) - callback-функция, которая будет вызвана, если


промис разрешен успешно. Эта функция принимает один аргумент - значение,
которое было передано функции resolve() .

onRejected (опциональный) - callback-функция, которая будет вызвана, если


промис был отклонен. Эта функция принимает один аргумент - значение,
которое было передано функции reject() .

Метод .then() возвращает новый промис, который будет разрешен или


отклонен в зависимости от того, что вернет функция обработки. Если функция
обработки возвращает значение, то новый промис будет разрешен этим
значением. Если функция обработки бросает исключение (throw), то новый
промис будет отклонен этим исключением.

.catch()
Метод .catch() позволяет обрабатывать ошибки в асинхронных операциях. Он
представляет собой сокращенную запись для обработки отклонений промисов и
является альтернативой использованию второго аргумента (onRejected) метода
then().
Он вызывается только в том случае, если промис был отклонен, и принимает один
аргумент - error.

promise.catch(onRejected)

promise.catch((error) => console.log(error)); // сработает в случае reject

6.3. Promise 4
где:

onRejected - callback-функция, которая будет вызвана, если промис был


отклонен. Эта функция принимает один аргумент - значение, которое было
передано функции reject().

Метод .catch() возвращает новый промис, который будет разрешен или


отклонен в зависимости от того, что вернет функция обработки. Если функция
обработки возвращает значение, то новый промис будет разрешен этим
значением. Если функция обработки бросает исключение (throw), то новый
промис будет отклонен этим исключением.

.finally()
Метод .finally() является одним из методов промисов и позволяет выполнить
определенное действие, когда промис завершается, независимо от того, был он
разрешен успешно или отклонен с ошибкой. То есть он отработает ВСЕГДА!!!

promise.finally(onFinally)

myPromise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log('Promise completed!'); //выполнится в любом случае
});

где:

onFinally - callback-функция, которая будет выполнена в любом случае. Она не


принимает аргументов. !!! На результат промиса никак не повлияет. !!!

Цепочка промисов
Цепочка промисов (Promise chaining) - это способ последовательного выполнения
нескольких асинхронных операций с помощью промисов. Этот подход позволяет

6.3. Promise 5
упростить и сократить код, а также делает его более понятным и
поддерживаемым.

const promise = new Promise(resolve => setTimeout(() => resolve(1), 2000));

promise
.then(data => data + 2)
.then(data => {
console.log(data) // 3
return data + 2;
})
.then(data => console.log(data)) // 5

Сейчас обговорим этот пример. Метод .then() возвращает промис,


соответственно к нему мы так же можем применить методы (then, catch, finally). По
умолчанию .then() и .catch() возвращают успешно завершенный промис
(fulfilled)

То есть я могу переписать пример выше вот так, и он по смыслу не поменяется

const promise = new Promise(resolve => setTimeout(() => resolve(1), 2000));

promise
.then(data => new Promise(resolve => resolve(data + 2)))
.then(data => {
console.log(data) // 3
return new Promise(resolve => resolve(data + 2))
})
.then(data => console.log(data)) // 5

Пример с .catch()
Пример 1
В примере ниже в консоли, если мы его запустим, увидим “1” и “2” .

const promise = Promise.reject();


promise
.catch(() => console.log("1"))
.then(() => console.log("2"))
.catch(() => console.log("3"))

6.3. Promise 6
Почему же так? Давай разбираться.
Промис завершается с ошибкой (reject), соответственно его обрабатывает
первый .catch() и выводит “1” . !!!Все, ошибки больше нет!! Дальше по цепочке
промис идет успешно завершенный (state: fulfilled). Соответственно следующим
выполнится метод .then() и выведет “2” в консоль и так же завершится успешно,
по этому последний .catch() не выполнится.

Пример 2
Теперь предлагаю рассмотреть второй пример. Как думаешь, что выведет в
консоль?

const promise = Promise.reject();


promise
.catch(() => {
console.log("1")
return Promise.reject();
})
.then(() => console.log("2"))
.catch(() => console.log("3"))

Промис завершается с ошибкой (reject), соответственно его обрабатывает


первый .catch() и выводит “1” , а дальше .catch() явно возвращает ошибку.
Соотвественно .then() его не обработает, и промис дойдет до следующего
.catch() . Таким образом правильный ответ “1” и “3”

Класс Promise
В классе Promise есть полезные статические методы:

1. Promise.resolve(value) : возвращает новый разрешенный promise с переданным


значением.

// вместо вот такой записи...


const promise = new Promise(resolve => resolve("Привет, Redev!"));

// ...можем создать промис вот так


const promise = Promise.resolve("Привет, Redev!");

6.3. Promise 7
2. Promise.reject(error) : возвращает новый отклоненный promise с переданной
причиной.

// вместо вот такой записи...


const promise = new Promise((resolve, reject) => reject("Ошибочка"));

// ...можем создать промис вот так


const promise = Promise.reject("Ошибочка");

3. : возвращает новый promise, который ожидает завершения


Promise.all(iterable)

всех промисов в передаваемом массиве. Если любой из промисов


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

const promise1 = new Promise(resolve => setTimeout(()=>resolve(1), 2000));


const promise2 = new Promise(resolve => setTimeout(()=>resolve(2), 1000));
const promise3 = new Promise(resolve => setTimeout(()=>resolve(3), 3000));

const result = Promise.all([promise1,promise2,promise3]);

result.then(data => console.log(data)); // [1, 2, 3]

В этом примере мы создаем три промиса, которые разрешаются через 2, 1 и 3


секунды соответственно. Затем мы передаем все три промиса в метод
. Когда все три промиса завершатся, метод Promise.all разрешится
Promise.all

с массивом значений разрешенных промисов в том порядке, в котором они


были переданы.

4. : возвращает новый promise, который ожидает


Promise.race(iterable)

завершения любого промиса в передаваемом массиве. Возвращаемый


promise разрешается или отклоняется в соответствии с результатом первого
завершенного промиса.
Коротко! Кто быстрее выполнится, результат того и вернется.
"Хто першы той лепшы” 😂
const promise1 = new Promise(resolve => setTimeout(()=>resolve(1), 2000));
const promise2 = new Promise(resolve => setTimeout(()=>resolve(2), 1000));
const promise3 = new Promise(resolve => setTimeout(()=>resolve(3), 3000));

6.3. Promise 8
const result = Promise.race([promise1,promise2,promise3]);

result.then(data => console.log(data)); // 2

В этом примере мы создаем 3 промиса: первый разрешается через 2 секунды,


второй разрешается через 1 секунду, а третий разрешается через 3 секунды.
Затем мы передаем три промиса в метод Promise.race . Когда первый промис
завершится, метод Promise.race разрешится или отклонится в соответствии с
результатом первого завершенного промиса.
Будет 2, потому что, второй промис выполнится быстрее остальных.

5. : принимает массив промисов и возвращает новый


Promise.allSettled(iterable)

промис, который разрешается, когда все промисы в массиве завершены,


независимо от их состояния (разрешен или отклонен).
Возвращает промис с результатом в виде массива объектов. Каждый объект
результата имеет два свойства:

, который может иметь значения "fulfilled" , если соответствующий


state

промис разрешен, или "rejected" , если он отклонен.

value, который содержит результат разрешенного промиса или причину


отклоненного промиса.

Пример использования Promise.allSettled :

const promises = [
Promise.resolve('Promise 1 resolved'),
Promise.reject('Promise 2 rejected'),
Promise.resolve('Promise 3 resolved')
];

Promise.allSettled(promises)
.then(results => {
console.log(results);
});

В этом примере мы передали массив, содержащий три промиса. Один промис


разрешен, другой отклонен, а третий промис разрешен. Когда метод
Promise.allSettled завершится, результат будет выведен в консоль в виде

массива объектов:

6.3. Promise 9
[
{state: "fulfilled", value: "Promise 1 resolved"},
{state: "rejected", reason: "Promise 2 rejected"},
{state: "fulfilled", value: "Promise 3 resolved"}
]

Этот пример демонстрирует, как метод Promise.allSettled разрешается


независимо от того, завершены ли переданные промисы успешно или нет.

Задания
1. Напиши функцию, которая получает на вход два числа и возвращает
Promise, который разрешается через 1 секунду с результатом суммы этих
чисел. Если одно из чисел не является числом, Promise должен быть
отклонен с ошибкой.

2. Напиши функцию getUser(id) , которая возвращает промис, который


разрешается (resolve) пользователем с заданным идентификатором, или
отклоняется с ошибкой, если пользователь не найден.

3. Напиши функцию sum(numbers) , которая возвращает промис, который


разрешается (resolve) суммой чисел в массиве, или отклоняется с
ошибкой, если массив пуст

4. Напиши функцию delayedGreeting(name, delay) , которая будет возвращать


Promise, который будет разрешаться (resolve) через заданный промежуток
времени delay и выводить на экран приветствие Hello, ${name}! .

5. Напиши функцию waitForAll(promises) , которая будет принимать массив


Promise и возвращать новый Promise, который разрешится (resolve), когда
все Promise из массива promises будут выполнены. Результатом
выполнения нового Promise будет массив результатов выполнения каждого
из Promise из исходного массива.

6. Что выведет в консоль и почему? (расписать в ответе)

6.3. Promise 10
Помоги сделать эту эту главу лучше! Дай обратную связь, а мы
прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/2W7LgHkfWLec3zdv6

🔄 6.4. async/await

6.3. Promise 11
🔄
6.4. async/await
Асинхронные функции (async/await) — это способ написания асинхронного кода,
который делает его более легким для чтения и написания, по сравнению с
использованием callback-ов или промисов.
Ключевые слова async и await в JavaScript предназначены для работы с
асинхронным кодом и облегчения его написания и понимания.
async используется для объявления асинхронной функции, которая возвращает
промис. Когда асинхронная функция вызывается, она начинает выполнение, и
затем возвращает промис, который может быть зарезолвлен или отклонен после
завершения выполнения функции.

awaitиспользуется для ожидания завершения выполнения промиса. Он должен


использоваться внутри асинхронной функции и перед вызовом другой
асинхронной функции, которая возвращает промис. await блокирует выполнение
функции до тех пор, пока промис не будет зарезолвлен или отклонен. Затем
значение промиса будет возвращено из await , и выполнение функции
продолжится.
Async/await позволяют нам написать асинхронный код так, как будто он
синхронный. Основная идея заключается в том, чтобы поместить асинхронный
код внутрь функции с ключевым словом async . Затем мы можем использовать
ключевое слово await для приостановки выполнения функции до тех пор, пока
асинхронный код не будет завершен.
Вот пример асинхронной функции, которая дожидается выполнения промиса 2
секунды и выводит результат в консоль:

const promise = new Promise(resolve => setTimeout(() => resolve(1), 2000));

async function getData() {


const data = await promise;
console.log(data);
}

6.4. async/await 1
getData();

В этом примере функция getData() использует await , чтобы приостановить


выполнение до тех пор, пока промис не будет завершен. Затем она выводит
данные в консоль.

Асинхронная функция возвращает успешно завершенный


промис.

async function asyncFunction() {


return 1;
}

asyncFunction().then(d => console.log(d))

// это тоже самое что и этот код

const promise = new Promise(resolve => resolve(1));

promise.then(d => console.log(d))

В асинхронной функции можно обработать ошибку от промиса new Promise с


помощью ключевого слова try/catch .

Пример:

const promise = new Promise((resolve, reject) => {


reject("Error")
});

async function asyncFunction() {


try {
const data = await promise;
console.log(data); // если бы не было ошибки, выполнился бы console.log(data)
} catch (error) {
console.log(error);// "Error"
}
}

В этом примере, мы используем await для ожидания выполнения промиса, и


затем оборачиваем код в блок try/catch . Если промис завершается успешно,
результат будет присвоен переменной data , и мы можем продолжить обработку.

6.4. async/await 2
Если же промис завершается с ошибкой, управление передается в блок catch ,и
мы можем обработать ошибку.

Задания
1. Напиши функцию, которая принимает на вход строку и возвращает промис,
который разрешается через указанное количество миллисекунд, где
количество миллисекунд равно длине строки.

2. Напиши функцию, которая принимает на вход число и возвращает промис,


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

3. Напиши функцию, которая получает на вход число и возвращает промис,


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

4. Напиши функцию, которая получает на вход два аргумента: строку и число.


Функция должна возвращать промис, который будет разрешен только после
того, как введенная строка будет выведена в консоль указанное количество
раз. Например, если функции переданы аргументы "hello" и 3, то промис
должен разрешиться только после того, как строка "hello" будет выведена в
консоль 3 раза.

5. Напиши функцию, которая принимает 2 промиса (оба успешно завершенных).


Первый возвращает твое имя, второй твою фамилию. Функция должна вернуть
успешно завершенный промис с имя + фамилия

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/VG39LX6ctzNnYipN7

🔂 6.5. Event Loop

6.4. async/await 3
🔂
6.5. Event Loop

Отличная статья на HABR с пояснением:


Рекомендую начать с нее! - https://habr.com/ru/post/501702/
Event Loop - это механизм в JavaScript, который позволяет обрабатывать
асинхронный код и управлять порядком выполнения задач в синхронном коде.

Зачем нужен Event Loop в JavaScript?

6.5. Event Loop 1


EventLoop в JavaScript нужен для асинхронной обработки событий и выполнения
задач. В отличие от синхронного кода, который выполняется по порядку,
асинхронный код выполняется в фоновом режиме, не блокируя поток выполнения.
Когда JavaScript выполняет код, он добавляет все задачи в очередь. EventLoop
следит за этой очередью и выполняет задачи по мере их поступления. Если
задача занимает много времени на выполнение, она не блокирует выполнение
других задач в очереди.
EventLoop позволяет выполнять асинхронные задачи, такие как загрузка данных
из сервера, анимация не прерывая главный поток выполнения. Благодаря этому
страницы загружаются быстрее и пользователи получают более отзывчивый
интерфейс.
Также, использование EventLoop позволяет избежать проблемы блокировки
выполнения кода, которая может возникнуть при выполнении синхронного кода.
Если синхронный код выполняется долго, пользователь может заметить
замедление работы приложения и получить отрицательный опыт использования.
Итак, EventLoop является важным механизмом для обеспечения плавной
работы асинхронного кода и повышения отзывчивости пользовательского
интерфейса.

Из чего состоит Event Loop?


Event Loop в JavaScript состоит из нескольких основных блоков:

1. Call Stack (стек вызовов) - это механизм, который используется для хранения
вызовов функций в порядке их вызова. Когда функция вызывается, она
помещается в вершину стека, а когда она завершается, она удаляется из
стека. Таким образом, стек вызовов используется для выполнения синхронного
кода в порядке вызова функций.

2. Web APIs (веб-интерфейсы) - это набор API-интерфейсов, предоставляемых


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

3. Callback Queue (очередь обратных вызовов) - это очередь, которая содержит


обратные вызовы, которые должны быть выполнены после завершения

6.5. Event Loop 2


асинхронной операции. Когда операция завершается, обратный вызов
добавляется в конец очереди.

4. Event Loop (цикл событий) - это механизм, который постоянно проверяет стек
вызовов и очередь обратных вызовов. Когда стек вызовов пуст, Event Loop
извлекает первый обратный вызов из очереди и помещает его в стек вызовов
для выполнения. Таким образом, Event Loop обеспечивает выполнение
асинхронного кода в правильном порядке и в том же самом потоке
выполнения.

Задания
1. Что попадет в микротаск, а что в макротаск?

2. В какой последовательности выполнятся console.log?

console.log(1);

setTimeout(() => console.log(2), 1000);

console.log(3);

new Promise((res) => res(4)).then((data) => console.log(data));

setTimeout(() => console.log(5), 2000);

Promise.resolve(6).then((data) => console.log(data));

new Promise((res) => setTimeout(() => res(7), 3000)).then((data) =>


console.log(data)
);

3. В какой последовательности выполнятся console.log?

setTimeout(() => console.log(5), 0);

new Promise((res) => res(1)).then((data) => console.log(data));

setTimeout(() => console.log(2), 1000);

Promise.resolve(3).then((data) => console.log(data));

console.log(4);

6.5. Event Loop 3


new Promise((res) => setTimeout(() => res(7), 2000)).then((data) =>
console.log(data)
);

for (let i = 0; i < 2; i++) {


console.log(i);
}

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму
https://forms.gle/48Zo4PJ3x79WqLjy6

🌐 6.6. HTTP (fetch)

6.5. Event Loop 4


🌐
6.6. HTTP (fetch)
HTTP - (англ. HyperText Transfer Protocol) — протокол передачи гипертекста. Когда
ты грузил эту страницу, ты (твой браузер) отправлял HTTP запросы и получал
ответы.
HTTP основан на технологии "клиент-сервер", что означает, что есть:

Клиенты, которые инициируют соединение и отправляют запросы;


front-end

Серверы, которые ждут соединений, обрабатывают запросы и возвращают


ответ. back-end

Структура HTTP-сообщения
Каждое сообщение HTTP состоит из трех частей, которые передаются в указанном
порядке:

стартовая строка, которая определяет тип сообщения;

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


другую информацию;

тело сообщения, которое содержит сами данные сообщения. Тело сообщения


должно отделяться от заголовков пустой строкой.

Более подробно можно почитать тут https://ru.wikipedia.org/wiki/HTTP

Методы
Тип HTTP-запроса (также называемый HTTP-метод) указывает серверу на то,
какое действие мы хотим произвести с ресурсом.

GET

6.6. HTTP (fetch) 1


POST

PUT

PATCH

DELETE

OPTIONS

HEAD

GET
Используется для получения информации с указанного источника.

Клиент может передавать параметры выполнения запроса в URI целевого ресурса


после символа “?”
GET /path/resource?param1=value1&param2=value2

const sendGetRequest = async () => {


try {
const response = await fetch('URL');
const data = await response.json();
console.log("data: ", data);
} catch (error) {
console.log("error: ", error);
}
}

POST
Используется для отправки информации, введенной пользователем, на сервер.
Например, при заказе пиццы 🍕
онлайн. Эта информация затем отправляется на
сервер с помощью метода POST и отображаются на странице пиццерии. Данные,
отправляемые на сервер (в примере с пиццей - заказ), включаются в тело запроса.
Также метод POST используется для загрузки файлов на сервер.

Пример в JavaScript с помощью fetch

const order = {
item: ['Peperoni'],
city: "Minsk",
telNumber: "+375291231231"

6.6. HTTP (fetch) 2


}

const sendPostRequest = async () => {


try {
const response = await fetch('URL', {
method: "POST",
headers: {
Authorization: "Bearer token"
},
body: JSON.stringify(order)
});
const data = await response.json();
console.log("data: ", data);
} catch (error) {
console.log("error: ", error);
}
}

PUT
Используется для загрузки содержимого запроса по указанному в запросе адресу
(URL). Если по этому адресу не существует ресурса, сервер будет создавать его и
возвращать статус 201 (Created). Если ресурс был изменен, сервер вернет 200
(Ok) или 204 (No Content).

Основная разница между методами POST и PUT :

PUT используется для создания или обновления ресурса на сервере. Когда


клиент отправляет PUT-запрос, сервер обновляет существующий ресурс или
создает новый, если он не существует.

POST используется для создания нового ресурса на сервере. Когда клиент


отправляет POST-запрос, сервер создает новый ресурс и возвращает клиенту
информацию о нем.

Пример в JavaScript с помощью fetch

const editOrder = {
item: ['Peperoni'],
city: "Brest",
telNumber: "+375291231231"
}

const sendPutRequest = async () => {


try {
const response = await fetch('URL', {

6.6. HTTP (fetch) 3


method: "PUT",
headers: {
Authorization: "Bearer token"
},
body: JSON.stringify(editOrder)
});
const data = await response.json();
console.log("data: ", data);
} catch (error) {
console.log("error: ", error);
}
}

PATCH
Аналогично PUT, но применяется только к фрагменту ресурса.
PATCH и PUT оба используются для обновления ресурсов на сервере
Однако они имеют разное поведение:

PUT используется для полной замены ресурса на сервере. Если клиент


отправляет запрос PUT на существующий ресурс, то сервер заменяет его
полностью на новый ресурс, который пришел в теле запроса. Если ресурс не
существует, то сервер создает его.

PATCH используется для частичного обновления ресурса. Если клиент


отправляет запрос PATCH на существующий ресурс, то сервер обновляет
только те части ресурса, которые были переданы в теле запроса. Если ресурс
не существует, то сервер должен возвращать ошибку.

В общем, использование PUT связано с полной заменой ресурса, а PATCH - с


частичным обновлением.
Пример в JavaScript с помощью fetch

const editOrder = {
city: "Brest",
}

const sendPatchRequest = async () => {


try {
const response = await fetch('URL', {
method: "PATCH",
headers: {
Authorization: "Bearer token"

6.6. HTTP (fetch) 4


},
body: JSON.stringify(editOrder)
});
const data = await response.json();
console.log("data: ", data);
} catch (error) {
console.log("error: ", error);
}
}

DELETE
Удаляет указанный ресурс.
Обычно DELETE запрос не имеет тела, но если необходимо, то может содержать.
Но это не является обязательным.

const sendDeleteRequest = async () => {


try {
const response = await fetch('URL', {
method: "DELETE",
headers: {
Authorization: "Bearer token"
}
});
const data = await response.json();
console.log("data: ", data);
} catch (error) {
console.log("error: ", error);
}
}

HEAD
Метод HEAD похож на метод GET, но в ответе сервера нет тела. Он обычно
используется для получения метаданных, проверки наличия ресурса и для
определения, изменился ли он с последнего обращения.

const sendHeadRequest = async () => {


try {
const response = await fetch('URL', {
method: 'HEAD'
});
console.log(response);
} catch (error) {

6.6. HTTP (fetch) 5


console.log(error);
}
}

OPTIONS
Метод OPTIONS используется для запроса сведений о доступных методах HTTP
для ресурса. Он может использоваться для получения списка поддерживаемых
методов или для проверки, поддерживает ли сервер определенный метод для
данного ресурса. Ответ сервера содержит заголовок Allow, который перечисляет
поддерживаемые методы. Метод OPTIONS часто используется в связке с методом
CORS (Cross-Origin Resource Sharing), чтобы указать браузеру, какие методы и
заголовки могут использоваться для кросс-доменных запросов.

const sendOptionsRequest = async () => {


try {
const response = await fetch('URL', {
method: 'OPTIONS'
});
console.log(response);
} catch (error) {
console.log(error);
}
}

Если кратко подытожить, то получается следующая картина:

GET - для получения ресурса.


POST - для создания ресурса.
PUT - для полного изменения ресурса.
PATCH - для частичного изменения ресурса.
DELETE - для удаления ресурса.
HEAD - для получения метаданных.
OPTIONS - для запроса сведений о доступных методах для ресурса.

Коды состояния HTTP

6.6. HTTP (fetch) 6


Коды состояния HTTP - это коды, которые возвращаются веб-сервером в ответ
на HTTP-запрос клиента. Они представляют собой целое число, которое
начинается с трех цифр. Например, 200 OK, 404 Not Found.

Коды состояния HTTP используются для того, чтобы указать клиенту, как
обрабатывать ответ сервера. Они показывают, был ли запрос успешным или нет, и
какую информацию необходимо получить из ответа. Например, код 200 OK
указывает на то, что запрос был успешным и в ответе содержится запрашиваемая
информация, а код 404 Not Found указывает на то, что запрашиваемый ресурс не
найден.

Категории
Все коды делятся на 5 основных классов, каждый из которых обозначается первой
цифрой кода:

1. 1xx (Informational): информационные коды, которые указывают на то, что


запрос был получен и продолжает обрабатываться.

2. 2xx (Successful): коды, которые указывают на успешное завершение запроса.


Например, 200 OK.

3. 3xx (Redirection): коды, которые требуют дополнительного действия от


клиента, например, перенаправление на другой URL.

4. 4xx (Client Error): коды, которые указывают на ошибку, вызванную


некорректным запросом клиента. Например, 404 Not Found.

5. 5xx (Server Error): коды, которые указывают на ошибку на стороне сервера.


Например, 500 Internal Server Error.

Каждый код состояния HTTP имеет свой смысл и определенное применение, и


клиент должен быть готов обрабатывать каждый код соответствующим образом

Наиболее часто встречающиеся. Я рекомендую их заучить!

"Успешно". Запрос успешно


200 Ok
обработан.
201 Created "Создано". Запрос успешно
выполнен и в результате был
создан ресурс.

6.6. HTTP (fetch) 7


"Множественный выбор".
Этот код ответа присылается,
300 Multiple Choice когда запрос имеет более
чем один из возможных
ответов.
"Перемещён на постоянной
основе". Этот код ответа
значит, что URI
301 Moved Permanently запрашиваемого ресурса был
изменён. Возможно, новый
URI будет предоставлен в
ответе.

"Плохой запрос". Этот ответ


означает, что сервер не
400 Bad Request
понимает запрос из-за
неверного синтаксиса.
"Неавторизованно". Для
получения запрашиваемого
ответа нужна
401 Unauthorized аутентификация. Статус
похож на статус 403, но,в
этом случае, аутентификация
возможна.

"Запрещено". У клиента нет


прав доступа к содержимому,
403 Forbidden
поэтому сервер отказывается
дать надлежащий ответ.
"Не найден". Сервер не
404 Not Found может найти запрашиваемый
ресурс.
сообщает о том, что сервер
418 I'm a teapot не может приготовить кофе,
потому что он чайник 😂
"Внутренняя ошибка
сервера". Сервер столкнулся
500 Internal Server Error
с ситуацией, которую он не
знает как обработать.

503 Service Unavailable "Сервис недоступен". Сервер

6.6. HTTP (fetch) 8


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

P.S По пожеланиям студентов ❤


Идемпотентность

Идемпотентность - это свойство запроса HTTP, которое определяет, будет ли


повторный запрос изменять состояние ресурса на сервере.

Методы POST и PUT используются для отправки данных на сервер, но они имеют
разное применение и разные свойства идемпотентности.

POST используется для создания нового ресурса на сервере. Этот метод не


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

PUT используется для обновления существующего ресурса на сервере. Этот


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

Куда передавать токен?


При выполнении HTTP-запросов, токен обычно передается в заголовке
Authorization . Это позволяет серверу проверить, что запрос был выполнен от

имени пользователя, который имеет доступ к запрашиваемому ресурсу.


Заголовок Authorization имеет следующий формат:

Authorization: <тип_авторизации> <токен>

6.6. HTTP (fetch) 9


Здесь <тип_авторизации> обозначает тип авторизации, например, Bearer ,и <токен> -
это сам токен, который вы хотите передать.

Пример использования заголовка Authorization при выполнении GET-запроса с


использованием Fetch API:

const token = 'my-token';

const sendGetRequest = async (token) => {


try {
const response = await fetch('URL', {
method: "GET",
headers: {
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
console.log("data: ", data);
} catch (error) {
console.log("error: ", error);
}
}

В этом примере мы передаем токен в заголовке Authorization с помощью Fetch


API.

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


HTTP-запросов (например axios), и передавать токен в заголовке Authorization
будет по-прежнему корректным способом аутентификации пользователя.

Задание
API documentation - https://first-node-js-app-r.herokuapp.com/api-docs/

Задача реализовать 6 функций по описанию ниже;


Цель: практика отправки запросов и работы с асинхронностью и научиться
пользоваться Swagger-ом;

1. Зарегистрировать пользователя

2. Авторизоваться - login (получить token)

6.6. HTTP (fetch) 10


3. Создать несколько todos

4. Получить список всех todos

5. Изменить одну таску

6. Удалить таску

* Для работы 3,4,5,6 нужен токен. Его можно получить один раз и
переиспользовать.
* Надо разобраться с документацие swagger. Что к чему там. Удачи 🍀
Полезное видео - https://www.youtube.com/watch?v=oXTPrWva9pc
Про Swagger - https://habr.com/ru/amp/post/434798/

Помоги сделать эту эту главу лучше! Дай обратную связь, а мы


прислушаемся к ней и сделаем ЛУЧШИЙ учебник по JavaScript для тебя и
остальных студентов!
Заполни форму

https://forms.gle/eTswQrw39piDCJUn8

6.6. HTTP (fetch) 11

Вам также может понравиться