Пытаемся в JS
Самое важное в JS:
Практически все сущности в JS — это объекты
Объект — набор свойств "имя:значение"
- Массив — это объект
- Функция — это объект
- Число — это объект*
- Строка — это объект*
*Ведут себя как объекты
Console.log
console — это объект, в объектах есть свойства, и каждое свойство — это пара "ключ:значение".
log — это метод, метод — это функция, которая является значением одного из свойств объекта
С помощью точечной записи можно получать доступ к свойствам объекта
console.dir() — отображает все свойства объекта
console.table() — отображает все свойства объекта в табличном виде
Любое выражение всегда возвращает значение
Выражение с побочными действиями возвращает не только значение, но и выполняет другие действия
Переменные
Переменные дают возможность повторного доступа к значениям
Названия переменных должны быть понятными
Имена переменных
PascalCase - типы и классы
DB_PASSWORD - значения известны до запуска приложения и не меняются
camelCase - все остальные переменные (используется чаще всего)
Объявление переменных
let - можно менять значения, по дефолту присваивается 'underfined'
const - нельзя менять значения (применять везде где это возможно)
Тип переменных определяется типом присвоенного значения
Отличие let, const и var
1) Переменные, которые мы объявляем через var можно обновлять и объявлять заново
2) Если переменная объявлена через var и она находится внутри функции, то область видимости этой переменной будет заканчиваться на этой функции соответственно и только
Область видимости var — это функция
Область видимости let и const — это блок
let и const можно объявлять лишь единожды
Примитивные типы
string (строка)
boolean (логический)
number (число)
null
underfined
symbol (символ)
Ссылочный тип
Если присвоить переменной значение объект, то переменная будет содержать в себе ссылку на этот объект, не его самого
Ссылочный тип
Ссылочный тип — это объект
Переменная, которой присваивается объект, в памяти будет хранить не сам объект, а ссылку на этот объект. Переменная будет хранить ссылку на объект, который будет находиться в другой части памяти
Динамическая типизация
const - выбор №1 в выборе типа переменной, чтобы не допустить возможных проблем в коде из-за динамической типизации (JS - это динамически типизируемый язык)
Правила работы с переменными
1. Все переменные объявлять перед их использованием
2. Стараться использовать const везде, где это возможно
Объекты
Объекты обладают свойствами
Если свойство содержит функцию как значение, то такое свойство называется метод
Практически все сущности в JavaScript - объекты
Объект - это набор свойств "имя:значение"
Объект - тип значений
Объект - тип переменных
Всегда для переменной выбирать const, если в ней будет содержаться объект как значение.
Порядок свойств в объектах не имеет значения, два объекта с одинаковыми свойствами и их значениями с разным расположением этих свойств технически считаются одинаковыми
Получение значений свойств
const myCity = {
city: 'New York',
popular: true,
country: 'USA'
}
Точечная запись/dot notation
Доступ к значению свойств через точку:
console.log(myCity.city) // 'New York'
console.log(myCity.popular) // true
Изменение свойств объекта через точку:
myCity.city = 'Los Angeles'
console.log(myCity.city) // 'Los Angeles'
Добавление новых свойств объекта через точку:
myCity.language = 'English'
console.log(myCity.language) // 'English'
Удаление свойств объекта через точку:
delete myCity.language = 'English'
console.log(myCity) // {city: 'Los Angeles', popular: true, country: 'USA'} (свойства 'language' больше НЕТ)
const myCity = {
city: 'New York',
info: {
popular: true,
country: 'USA'
}
}
Доступ к значению свойств через скобки:
Доступ к значению свойства с использованием скобок необходимо в том случае, если название свойства является значением той или иной переменной
myCity.info['popular'] = false
Использование переменных при формировании объекта
Можно использовать переменные в качестве значений для свойств объекта, также в качестве значений для свойств объекта можно использовать любые выражения
сonst name = 'Tim'
const postsQty = 23
const userProfile = {
name: name,
postsQty: postsQty,
hasSignedAgreement: false
}
const userProfile = {
name,
postsQty,
hasSignedAgreement: false
}
Сокращенные свойства рекомендуется располагать в начале объекта
Глобальные объекты
window – веб-браузеры
global – node.js
globalThis – унифицированный глобальный объект
К свойствам глобальных объектов можно обращаться без приписки "window" или "global": интерпретатор поймет, что происходит попытка обращения к свойству глобального объекта
Методы объекта
Метод - свойство объекта, значение которого — функция
Методы можно вызывать
const myCity = {
city: 'New York',
greetings: function () {
console.log('Greetings!!')
}
}
myCity.greentings() // 'Greetings!!'
myCity.greentings() — вызов метода
myCity.city — доступ к значению свойства
JSON
Мутирование объектов
Объект — ссылочный тип, переменная хранит ссылку на объект => можно менять значение тех или иных свойств — это и называется мутация объекта, на который ссылается переменная
Мутация копий — возможность мутирования объекта, используя копию переменной, к которой ссылается объект
Как избежать мутаций
const person = {
name: 'Bob',
age: 25
}
При таком раскладе, если у объекта есть вложенные свойства, то ссылки на них сохраняются — мы можем избежать мутирования лишь корневых свойств объекта
const person = {
name: 'Bob',
age: 25
}
console.name(person.name) // 'Bob'
console.name(person2.name) // 'Alice'
Ссылки на вложенные объекты сохраняются, также, как и в варианте 1
const person = {
name: 'Bob',
age: 25
}
const person2 = JSON.parse(JSON.stringify(person))
console.name(person.name) // 'Bob'
console.name(person2.name) // 'Alice'
Ссылки на вложенные объекты в этом варианте НЕ СОХРАНЯЮТСЯ
Функции
Функция - блок кода, который можно выполнять многократно.
Функция может быть:
Именованной;
Присвоена переменной;
Анонимной;
Аргументом при вызове другой функции;
Значением свойства (метода) объекта
Функция - это объект
Функция возвращает underfined, если в ней нет инструкции return
Передача значений по ссылке
const personOne = {
age: 21,
name: 'Bob'
}
function uncreasePersonAge (person) {
person.age += 1
return person
}
uncreasePersonAge(personOne)
console.log(personOne.age) // 22
Внутри функции выше мы мутируем внешний объект, что делать НЕ рекомендуется
const personOne = {
name: 'Bob',
age: 21
}
function uncreasePersonAge(person) {
const updatedPerson = Object.assign({}, person)
updatedPerson.age += 1
return updatedPerson
}
const updatedPersonOne = uncreasePersonAge(personOne)
console.log(personOne.age) // 21
console.log(updatedPersonOne.age) // 22
Колбэк функции
Колбэк функции - функции, которые вызывают внутри себя другие функции
function anotherFunction() = {
// Действия...
}
function callBackAnotherFn(callBackFunction){
callBackFunction()
}
Правила работы с функциями
1. Называть функции исходя из выполняемых задач
2. Одна функция должна выполнять одну задачу
3. Не рекомендуется изменять внешние относительно функции переменные
Область видимости
Область видимости определяет границы действия переменной
Есть глобальные переменные (объявленные в глобальной области видимости) и локальные переменные (объявленные в локальной области видимости)
Правила работы с переменными
1. Все переменные объявлять перед их использованием
2. Стараться использовать const везде, где это возможно
3. Внутри функций не изменять переменные с внешних областей видимости
Операторы
Символьные:
1. Арифметические:
"+" — сложить
"-" — отнять
"/" — поделить
"*" — умножить
2. Сравнения:
"===" — равно
"!==" — не равно
"<=" — меньше либо равно
">=" — больше либо равно
3. Логические:
"!" — не
"&&" — и
"||" — или
4. Присваивания:
"=" — присвоить
Текстовые:
1. typeof — с помощью него можно проверить тип того или иного значения 2. instanceof — с помощью него можно проверить принадлежность объекта к тому или иному классу 3. new — 4. delete —
Операторы короткого замыкания
Оператор &&
Выражение 1 && Выражение 2
Если "Выражение 1" ложно:
1. Выражение 2 игнорируется
2. Возвращается результат "Выражения 1"
Мы ищем первое ложное значение
Если "Выражение 1" истинно, а "Выражение 2" ложно, возвращается результат "Выражения 2", также, как и если бы "Выражение 2" было бы истинно
Оператор ||
Если "Выражение 1" истинно:
1. Выражение 2 игнорируется
2. Возвращается результат "Выражения 1"
Мы ищем первое истинное значение
Если "Выражение 1" ложно, а "Выражение 2" истинно, возвращается результат "Выражения 2", также, как и если бы "Выражение 2" было бы ложно
Трюк с оператором & и вызовом функции
b && console.log('Done!')
Это то же что и конструкция if, но в одну строчку кода
Оператор разделения объекта на свойства "..."
const button = {
width: 200,
text: 'Buy'
}
В случае присутствия в объекте 'button' свойства 'color', значение этого свойства будет перезаписано на 'red'
Оператор разделения объекта на свойства позволяет также объединять объекты, более того, он позволяет избежать мутирования, если в исходных объектах, которые мы объединяем, нет вложенных объектов.
Конкатенация строк
Оператор "+" для объединения строк:
Также можно использовать переменные при конкатенации строк:
Шаблонные строки
В примере выше может быть любое выражение, например, вызов функции
Функциональные выражения
Отличие объявленной функции и функционального выражения заключается в том, что у второго отсутствует имя, они всегда анонимные, их нельзя использовать автономно, используются чаще всего как аргумент в вызове другой функции (колбэк функции)
Функциональное выражение в вызове другой функции
setTimeout(function() {
console.log('Отложенное сообщение')
}, 1000)
// 'Отложенное сообщение' будет выведено в консоль через 1000 мс (1 сек)
Стрелочные функции
Стрелочная функция - это выражение, стрелочная функция всегда анонимная
Как дать имя стрелочной функции?
const myFunction = (a, b) => {
let c
a = a + 1
c = a + b
return c
}
Почему стоит присваивать переменной функциональное выражение или стрелочную функцию и почему не стоит использовать традиционное объявление функции?
Если объявлять переменную используя "const", будет невозможно присвоения нового значения для этой переменной, благодаря этому можно предотвратить случайное изменение значения такой переменной
Если объявлять функцию традиционно через function и сразу же давать ей имя, возможно присвоение нового значения для этой переменной
Использование стрелочной функции в качестве колбэк-функции (использование стрелочной функции в вызове другой функции)
setTimeout(() => {
console.log('Отложенное сообщение')
}, 1000)
// 'Отложенное сообщение' будет выведено через 1000 мс (1 сек)
Сокращение стрелочных функций
Если один параметр, то круглые скобки можно опустить:
Так делать нежелательно, поскольку читабельность кода становится в разы сложнее
Если тело функции состоит из одного выражения, фигурные скобки можно опустить
Значения параметров функции по умолчанию
function multByFactor(value, multiplier = 1) {
return value * multiplier
}
const myNewPost = (person, date = Date()) => ({
...person,
addedDate, // (сокращенный формат записи свойства объекта)
}) (оборачиваем в скобки, чтобы функция вернула новый объект неявно)
Обработка ошибок
Что происходит в случае ошибок
try/catch
const fnWithError = () => { throw new Error('Some error'); }
try { fnWithError(); } catch (error) {
console.error(error); console.log(error.message); }
console.log('Continue...');
В данном случае наша ошибка обойдет проблемы uncaught error (не пойманная ошибка) и мы с ней сможем поработать.
Инструкции
Выражение всегда возвращает значение.
Инструкция выполняет действие. Каждую инструкцию следует разделять точкой с запятой.
Как отличить выражение от инструкции
Выражение может быть использовано в качестве аргумента при вызове функций
Массивы
Массив — это объект с цифровыми именами свойств
const myArray = [1, 2, 3]
console.log(myArray) // [1, 2, 3]
constmyArray2 = new Array(1, 2, 3)
console.log(myArray) // [1, 2, 3]
Структура массива
Абсолютно индентичные массивы с одиннаковым и равным количеством элементов не равны между собой, так как они ссылаются на разные объекты в памяти
Массив vs объект
Массивы и объекты визуально совпадают, но у них разные прототипы и разное поведение
Чтение значений массива
const myArray = [1, true, 'a']
console.log(myArray) = // [1, true, 'a']
Порядок элементов в массиве важен, потому что каждый элемент в массиве имеет свой порядковый номер, который называется индексом, поэтому порядок следования элементов в массиве важен.
Изменение и добавление элементов массива
const myArray = [1, 2, 3, 4]
console.log(myArray.length) // 4
console.log(myArray) // [1, 2, 'abc, 4]
console.log(myArray.length) // 4
Методы массивов
Функции высшего порядка в массивах/функции прототипов/методы прототипов
push
pop
shift
unshift
Each
map
Каждый массив, который мы создаем, является экземпляром массива, на уровне массива определены множество методов, которые доступны для всех массивов, методы можно вызывать используя точечную запись.
LENGTH
Позволяет нам узнать длину массива
Также с помощью метода length можно укорачивать исходный массив
Применение массивов
1) Очередь/ упорядоченная коллекция элементов
Очередь поддерживает 2 вида операций
- Добавление элементов в конец очереди
- Удаление элементов в начале, сдвигая очередь так, что второй элемент становится первым
2) Структура данных Стек
Стек поддерживает 2 вида операций
Массивы в JS могут работать и как очереди, и как стек
PUSH
Добавляет новый элемент/несколько элементов в конец массива
POP
Удаляет последний элемент массива и возвращает его
const removedElement = myArray.pop()
console.log(myArray) // [1, 2]
console.log(removedElement) // 3
UNSHIFT
Добавляет элемент в начало массива (редко используется)
SHIFT
Удаляет первый элемент массива сдвигая все оставшиеся элементы массива влево (первый стал нулевым, второй первым и тп) и возвращает его
const myArray = [true, 1, 2, 3, 4]
Метод splice
1) Удаляет конкретный элемент массива и возвращает его
myArray.splice(a, b, c, ..., n), где
a — стартовая позиция (ключ)
b — количество элементов, которые мы хотим удалить
const myArray = [true, 1, 2, 3, 4]
const removerElem = myArray.splice(3, 1)
console.log(removedElem) // 3
console.log(myArray) // [true, 1, 2, 4]
2) Заменяет конкретный элемент массива
3) Добавляет элементы в массив
4) Удаляет элемент массива с конца
Метод slice
Возвращает новый массив, в который копирует все элементы, начиная со start
до end
не включительно. Оба индекса start
и end
могут быть отрицательными. В таком случае отсчёт будет осуществляться с конца массива.
const newArr = myArr.slice([1], [2])
const newArr2 = myArr.slice([-2],[-1])
const newArr3 = myArr.slice([-1])
console.log(newArr) // [2]
console.log(newArr2) // [3]
console.log(newArr3) // [4]
Можно вызвать slice
и вообще без аргументов: myArr.slice()
создаёт копию массива myArr
. Это часто используют, чтобы создать копию массива для дальнейших преобразований, которые не должны менять исходный массив.
Метод concat
Метод arr.concat
создаёт новый массив, в который копирует данные из других массивов и дополнительные значения:
Он принимает любое количество аргументов, которые могут быть как массивами, так и простыми значениями.
В результате мы получаем новый массив, включающий в себя элементы из arr
, а также arg1
, arg2
и так далее…
Если аргумент argN
– массив, то все его элементы копируются. Иначе скопируется сам аргумент.
const newArr = myArr.slice([1], [2]) // 2
const newArr2 = myArr.slice([-1]) // 4
let includeArr = myArr.concat(newArr, newArr2) // [1, 2, 3, 4, 2, 4]
Поиск в массиве
indexOf/lastIndexOf и includes
arr.indexOf(item, from)
ищетitem
, начиная с индексаfrom
, и возвращает индекс, на котором был найден искомый элемент, в противном случае-1
.arr.lastIndexOf(item, from)
– то же самое, но ищет справа налево.arr.includes(item, from)
– ищетitem
, начиная с индексаfrom
, и возвращаетtrue
, если поиск успешен.
const myArr = ['Tim', 'Den', 'Jake', 'Mike']
console.log(myArr.indexOf('Mike')) // 3
console.log(myArr.lastIndexOf('Mike')) // 3
console.log(myArr.includes('Mike')) // true
console.log(myArr.indexOf('Mike', 2)) // 3
console.log(myArr.lastIndexOf('Den', 2)) // 1
console.log(myArr.includes('Den', 2)) // false
Find и findIndex
let result = arr.find(function(item, index, array) {
// если true - возвращается текущий элемент и перебор прерывается
// если все итерации оказались ложными, возвращается undefined
});
Метод arr.findIndex – по сути, то же самое, но возвращает индекс, на котором был найден элемент, а не сам элемент, и -1
, если ничего не найдено.
const myArrWithObj = [ {name: 'Tim', age: 21}, {name: 'Jake', age: 25}, {name: 'Juan', age: 23}, ]; const returnCorrectAge = myArrWithObj.find(item => item.age === 21); console.log(returnCorrectAge); // { name: 'Tim', age: 21 } const returnCorrectIndex = myArrWithObj.findIndex(item => item.age === 23); console.log(returnCorrectIndex); // 2
Метод Filter
Метод find
ищет один (первый попавшийся) элемент, на котором функция-колбэк вернёт true
.
На тот случай, если найденных элементов может быть много, предусмотрен метод arr.filter(fn).
Синтаксис этого метода схож с find
, но filter
возвращает массив из всех подходящих элементов:
let results = arr.filter(function(item, index, array) { // если true - элемент добавляется к результату, и перебор продолжается // возвращается пустой массив в случае, если ничего не найдено });
const myArrWithObj = [ {name: 'Tim', age: 21}, {name: 'Jake', age: 25}, {name: 'Juan', age: 23},]; const returnCorrectAge = myArrWithObj.filter(item => item.age > 21); console.log(returnCorrectAge); // [ { name: 'Jake', age: 25 }, { name: 'Juan', age: 23 } ] console.log(returnCorrectAge.length); // 2
Методы сортировки массивов
Метод Sort()
Элементы по умолчанию сортируются как строки.
Сортировка массива по возрастанию
const myArr = [4, 13, 3, 763, 94]; const myArr1 = myArr.sort((a, b) => { return a - b });
Метод reverse()
Метод arr.reverse меняет порядок элементов в arr
на обратный.
let arr = [1, 2, 3, 4, 5]; arr.reverse(); alert( arr ); // 5,4,3,2,1
Он также возвращает массив arr
с изменённым порядком элементов.
Метод map
map — очень популярный метод, с помощью которого можно перебрать все элементы массива и выполнить определенные действия с этими элементами, при этом изменяя элементы массива.
Вызывает функцию для каждого элемента массива и возвращает новый массив с результатами выполнений этой функции
Функция, возвращающая первые символы элементов массива
const myArr = ['Tim', 'Dan', 'Jake'];
const myArr1 = myArr.map((item, index, arr) => { return item[0] });
item - каждый элемент массива
index - ключ/позиция каждого элемента массива
arr - массив, с которым работаем
Split и join
Split - преобразовывает строку в массив по заданному разделителю.
Преобразование строки в массив:
const stringVal = 'Boba,Buba,Biba'
const myArr = stringVal.split(',') console.log(myArr);
Join - преобразовывает массив в строку с заданным разделителем.
Преобразование массива в строку:
const arrVal = ['Boba', 'Buba', 'Biba']
const myArr = arrVal.join(', ') console.log(myArr);
Метод isArray
Проверка массива на принадлежность к типу данных "массив":
const arr = []const obj = {} const typeCheck = (val) => { if (Array.isArray(val)) { console.log('Это массив') } else { console.log('Это не массив') } }
typeCheck(arr)typeCheck(arr) // 'Это массив' typeCheck(obj)typeCheck(obj) // 'Это не массив'
Перебор массива
Метод forEach
forEach— очень популярный метод, с помощью которого можно перебрать все элементы массива и выполнить определенные действия с этими элементами, но при этом сам массив не меняется.
forEach - выполняет функцию для каждого элемента массива.
const myArr = ['Биба', 'Боба', 'Бэбрик'];
myArr.forEach((item, index, array) => { console.log(`${item} находится на ${index} позиции в ${array}`) });
Также при работе с forEach в аргументах мы можем указывать имя функции, с который впоследствии мы можем работать.
Reduce и reduceRight
Данные методы используются для вычисления какого-нибудь единого значения на основе всего массива.
let value = arr.reduce(function(previousValue, item, index, array) { // ... }, [initial]);
Функция применяется по очереди ко всем элементам массива и «переносит» свой результат на следующий вызов.
const myArr = [1, 2 , 3, 4]
const res = myArr.reduce((previousValue, item, index, array) => { return previousValue + item; }, 0) console.log(res) // 10
Если начальное значение (previousValue) не указано, по умолчанию оно становится равным первому элементу массива.
Метод reduceRight работает аналогично с методом reduce, но проходит массив справа налево
Деструктуризация
Деструктуризация объектов
Как присвоить некоторые значения свойств объекта переменным:
const myObj = { nameOf: 'Tim', age: 21, sex: 'Male', learnJs: true, }
const {nameOf, sex} = myObj /* в ф. скобках можно указать одно, все: любые свойства объекта */
console.log(nameOf) // 'Tim' console.log(sex) // 'Male'
Используя такой синтаксис можно объявить переменную и одновременно присвоить им значения на основе значений свойств объекта.
Деструктуризация массивов
const myArr = ['Orange', 'Coconut'] const [myArrOne, myArrTwo] = myArr
/* Важно понимать, что в отличие от объектов, порядок элементов массива важен. Поэтому необходимо учитывать этот факт при деструктуризации массивов*/
console.log(myArrOne) // 'Orange' console.log(myArrTwo) // 'Coconut'
Деструктуризация параметров функции
const myObj = { nameOf: 'Tim', comments: 23, work: true, sex: 'Male' }
const objObj = { nameOf: 'Jack', work: false, sex: 'Male' }
const howManyComments = ({comments, work, nameOf}) => { // здесь нет необходимость указывать let или const в блоке параметров потому что мы знаем, что параметры это и есть переменные, значения которых меняются при вызове функции if (!work) { return `User ${nameOf} hasn't comments` } return `User ${nameOf} has ${comments} comments` }
console.log(howManyComments(myObj)) // User Tim has 23 comments console.log(howManyComments(objObj)) // User Jack hasn't comments
В данном примере в блоке аргументов объявления функции мы можем выполнить деструктуризацию элементов входного объекта при вызове функции. Мы хотим взять свойства с именами nameof, work, comments из значения которое будет передано в вызове функции (объект), создать новые переменные с названиями nameof, work, comments и присвоить им соответсвующее значение.
Условные инструкции
Инструкция if
if (условие) {
// Блок кода, выполняемый однократно, если Условие правдиво
}
Популярное использование условной конструкции if
if (!person.name) {
console.log("Имя не указано")
// Другие действия в случае, если свойства 'name' у объекта 'person' нет
}
Инструкция if else
if (условие) {
// Блок кода, выполняемый однократно, если Условие правдиво
} else {
// Блок кода, выполняемый однократно, если Условие ложно
}
Инструкция if else if
if (Условие 1) {
// Блок кода, выполняемый однократно, если Условие 1 правдиво
} else if (Условие 2) {
// Блок кода, выполняемый однократно, если Условие 2 правдиво
} else {
// Блок кода, выполняемый однократно, если предыдущие условия ложны
}
Использование if в функциях
Популярный подход использования if в функциях:
const sumPositiveNumbers = (a, b) => {
if ((typeof a !== 'number') || (typeof b !== 'number')) {
return 'Один из аргументов не число'
}
if ((a <= 0) || (b <= 0)) {
return 'Один из аргументов не положительное число'
}
Инструкция switch
switch (Выражение) {
case A:
// Действия если Выражение === A
break
case B:
// Действия если Выражение === B
break
default:
// Действия по умолчанию
}
Тернарный оператор
Конструкция с тернарным оператором — выражение (выражение всегда возвращает значение)
Условие — любое выражение
Если условие правдиво, то возвращается результат Выражения 1
Если условие ложно, то возвращается результат Выражения 2
Второй, более предпочтительный способ:
value
? console.log('Условие истинно')
: console.log('Условие ложно')
Циклы
Типы циклов
for
for..in..
while
do..while
for..of..
For
for (Начальная инструкция; Условие; Итерационное действие) {
// Блок кода, выполняемый на каждой итерации
}
Для перебора массивов не нужен for
const myArray = ['first', 'second', 'third']
for (let i = 0; i < myArray.length; i++) {
console.log(myArray[i])
}
Для работы с массивами можно использовать циклы, но этого делать не рекомендуется. Лучше использовать функции высшего порядка для массивов ('forEach', 'map', 'reduce')
const myArray = ['first', 'second', 'third']
myArray.forEach((element, index) => {
console.log(element, index)
})
While
while (Условие) {
// Блок кода, выполняемый на каждой итерации
}
Do while
do {
// Блок кода, выполняемый на каждой итерации
} while (Условие)
Цикл do while необходимо использовать, если мы хотим повторить действие хотя бы раз
For in
for (key in Object) {
// Действия с каждым свойством объекта
// Действия свойства — Object[key]
}
const myObject = {
x: 10,
y: 15,
z: 20
}
for (const key in myObject) {
console.log(key, myObject[key])
}
For in для объектов
Получение всех ключей объекта в виде массива
const myObject = {
x: 10,
y: true,
z: 'abc'
}
Object.keys(myObject).forEach(key => {
console.log(key, myObject[key])
})
Объекты возможно преобразовывать в массивы, используя методы keys и values
For in для массивов
For of
for (Element of Iterable) {
// Действия с определенным элементом
}
Пример применения for of для строки
Пример применения for of для массива
const myArray = [true, 10, 'abc', null]
For of НЕ подходит для объектов, так как объект это неитерируемый элемент в JS
Модули
Модули позволяют структурировать код, избегать дублирования блоков кода.
Import & export
Экспорт по умолчанию
Классы и прототипы
Синтаксис классов появился в ES6
class ...
- Классы позволяют создавать прототипы для объектов
- На основании прототипов создаются экземпляры
- Экземпляры могут иметь свои собственные свойства и методы
- Экземпляры наследуют свойства и методы прототипов
Название классов начинается с паскаль-кейса (с большой буквы)
class Comment { constructor(text){ this.text = text; this.votesQty = 0; } upvote(){ this.votesQty += 1; } }
Создание экземпляров класса
Мы можем создать экземпляр класса с помощью ключевого слова new:
const firstComment = new Comment('First comment');
Собственные свойства экземпляра
Наследование по цепочке
Цепочка прототипов
Проверка пренадлежности классу
Чтобы проверить, пренадлежит ли классу экземпляр, мы можем воспользоваться методом instanceof:
Вызов унаследованных методов
Проверка принадлежности свойств экземпляру объекта
Чтобы проверить, пренадлежит ли экземпляру свойство, мы можем воспользоваться методом hasOwnProperty:
Статические методы
Главное различие статических методов и унаследованных методов — статические методы не наследуются экземплярам, на уровне экземпляров мы не можем к ним обратиться. Унаследованные методы всегда наследуются экземплярам и доступны на их уровне.
Расширение других классов
Прототип
Прототипы - это механизм, с помощью которого объекты JavaScript наследуют свойства друг от друга.
Промисы
Промисы позволяют обрабатывать отложенные во времени события.
Промис - это обещание предоставить результат позже.
Промис может вернуть ошибку, если результат предоставить невозможно.
Состояния промиса
Создание и использование промисов
Получение результата промиса
Вызов fetch внутри промиса
ASYNC/AWAIT
Async/await — специальный синтаксис для упрощения работы с промисами
Асинхронная функция
Асинхронная функция — это функция, которая возвращает промис
Использование await внутри асинхронных функций
В асинхронных функциях можно использовать ключевое слово await:
Ожидание результата await
Переход с промисов на async/await
В примере выше нет обработки ошибок:
Обработка ошибок в асинхронных функциях
Главное в async/await
- async/await — это синтаксическая надстройка над промисами
- await синтаксис возможен только внутри async функций
- async функция всегда возвращает Promise
- async функция ожидает результата инструкции await и не выполняет последующие функции
Всё что не видео-курс
__proto__ vs prototype
prototype- это объект.
__proto__ - это объект, который ссылается на какой-то прототип.
__proto__
__proto__ есть у всех объектов:
a = {}; // a.__proto__ b = []; // b.__proto__ c = 18; // c.__proto__ d = 'abc' // d.__proto__ function e(){} // e.__proto__ let f = function(){}; // f.__proto__ let g = () => {}; // g.__proto__ class h {} // h.__proto__ let i = true // i.__proto__
Что такое __proto__?
Разные __proto__ разных по типу объектов - совершенно независимые разные объекты. У одинаковых по "типу" объектов - они равны, то есть это один и тот же объект.
Любой объект создается с помощью конструктора либо класса.
Чтобы понимать, что это за __proto__, нужно ТОЧНО знать с помощью какой функции-конструктора (класса) создан данный объект.
Каждый prototype - это независимый объект, сам по себе, с определенным набором свойств и методов.
Т.е. __proto__ есть у каждого объекта, а prototype есть либо у class либо у function.
__proto__ любого объекта ссылается на prototype класса (или функции-конструктора), с помощью которой этот объект был создан (сконструирован).
Зачем классу нужен объект prorotype
Зачем объектам, созданным с помощью этого класса, нужно свойство __proto__, которое ссылается на этот объект prototype
Если мы пытаемся прочитать свойство объекта, либо вызвать его метод, а данного свойства/метода нет, то объект полезет искать его через ссылку __proto__ в prototype класса, с помощью которого он был создан.