JavaScript
Выполнять кода в: VS Code, Браузер, Node.js
Интерпретатор запускает файл JS два раза:
Этап 1 — Фаза подготовки (создания контекста / hoisting) Интерпретатор просматривает весь код, но ещё ничего не выполняет.
Находит объявления функций (function declarations) — и создаёт их сразу. Находит объявления переменных (var, let, const) — но: var создаются и ставятся в undefined; let и const создаются, но не инициализируются (зона TDZ — temporal dead zone). Это называется поднятие (hoisting).
Этап 2 — Фаза выполнения (execution phase) Теперь код выполняется построчно сверху вниз. Интерпретатор:
назначает значения переменным; вызывает функции; выполняет операции, условия, циклы и т.д.
Выражение:
Выражение возвращает значение
console.log('Привет')
// однострочный комментарий
/* многострочный
комментарий */
// console - объект
// . - точечная запись, способ получения доступа к свойствам объекта
// log - метод - это функция которая является одним из свойств объекта
// () вызов метода
// 'Привет' - аргумент
Переменные:
Наименование переменных: PascalCase - для типов и классов DB_PASSWORD - когда значения известны до запуска приложения и не меняются во время работы camelCase - все остальные случаи
Объявление переменных:
'use strict' // инструкция в начале кода которая (включает строгий режим
// исполнения кода.) запрещает использовать необъявленные переменные
let // переменная возможно пере присвоить значение
const // переменная с неизменным значением, при попытке изменить выдаст ошибку
var // старый формат объявления переменой
let a, b
a = true // присвоение переменной
const a = 10 // объявление переменой и присвоение переменной, переменную const сразу требует присвоения значения иначе ошибка.
Области видимости:
Глобальная область видимости (Global scope) Переменные, объявленные вне функций, доступны во всём коде. В браузере глобальные переменные становятся свойствами объекта window.
Функциональная область видимости (Function scope) Переменные, объявленные с помощью var внутри функции, видны только внутри этой функции.
Блочная область видимости (Block scope) Переменные, объявленные через let или const, видны только внутри блока { … }
Лексическая область видимости (Lexical scope) JS использует лексический (статический) scope — область видимости определяется местом объявления, а не местом вызова.
Замыкания (Closures) Функция «запоминает» область видимости, в которой была создана.
Типы переменных:
Примитивный тип - хранит непосредственно значение в переменной (Копируются полностью при присваивании., Изменение одной переменной не влияет на другую.)
string // строка, 'строка'
boolean // логическое, true, false
number // число, 1 подсвечивает в консоли синим
null // значение - ничего, null, можно использовать как сброс значения
symbol // символ, Symbol('любой текс') два одинаково написанных символа это два разных объекта. Используется чтоб не перезаписать значение например при разных библиотеках
undefined // нет значения (не определено)
bigint // очень большие числа, обычные числа до ±2^53
console.log(Number.MAX_SAFE_INTEGER) // максимальное целое число 9007199254740991
console.log(90071992547409919007199254740991n) // выдаст 90071992547409919007199254740991
console.log(90071992547409919007199254740991n + 1n) // не может быть смешан с другими типами
Ссылочные типы - хранит ссылку на объект в памяти, а не сам объект. (Если присвоить объект другой переменной, обе переменные смотрят на один и тот же объект.)
object // объект с ключами и значениями
array // массив (особый объект)
function // функция тоже объект
Динамическая типизация
let a = 'abc'; // строка
a = 10; // теперь число
Функция и её переопределение
let b = () => console.log('Привет');
// => — выполни то, что справа, это стрелочная функция (arrow function)
b = 10; // теперь b — число
// b(); // ошибка! b уже не функция
const нельзя менять
const c = () => console.log('Привет');
// c = 10; // ошибка! const нельзя переназначить
c(); // Привет
Объекты:
Порядок свойств в объекте не имеет значения
const objectA = { // объект
a: 10, // свойства объекта
b: true // свойства объекта
}
objectA.a // доступ к значению через точку
objectA.a = 20 // пере присваивание
objectA.с = 'Новое' // новое свойство объекта
delete objectA.a // удаление свойства объекта
objectA['new_svoistvo'] = true // добавление свойство (не соответствует правилам идентификатора)
// Не соответствует:
// имя начинается с цифры,
// есть пробелы или дефис или сец.символ,
// имя хранится в переменной
Имя хранится в переменной
// Создаём пустой объект
const objectA = {}; // сейчас объект пустой: {}
// Создаём переменную key со значением 'color'
const key = 'color'; // key = 'color', это просто значение, пока нет ячейки в объекте
// Через точку создаём ячейку с буквальным именем "key"
objectA.key = 'blue';
console.log(objectA.key); // 'blue' ← обращаемся к ячейке "key"
console.log(objectA.color); // undefined ← ячейки "color" ещё нет
// objectA сейчас выглядит так: { key: 'blue' }
// Через квадратные скобки создаём ячейку с именем из переменной key ('color')
objectA[key] = 'green';
console.log(objectA.color); // 'green' ← теперь есть ячейка "color"
console.log(objectA.key); // 'blue' ← ячейка "key" осталась без изменений
// objectA сейчас выглядит так: { key: 'blue', color: 'green' }
Объект с вложенной структурой
// Создаём объект с вложенной структурой
const myCity = { // объект
name: 'Moscow', // свойство 1 уровня
info: { // свойство 1 уровня, внутри ещё один объект
isPopular: true, // свойство 2 уровня
country: 'Russia' // свойство 2 уровня
}
};
// Доступ к вложенным свойствам
console.log(myCity.name); // "Moscow"
console.log(myCity.info.isPopular); // true
console.log(myCity.info.country); // "Russia"
Сокращенные объекты
const name = "Bog"; // переменная name
const fname = "Bof"; // переменная fname
// создаём объект
const userProf = {
name, // сокращённая запись: name: name (свойство совпадает с именем переменной)
fname, // сокращённая запись: fname: fname
};
// сокращенные свойства рекомендуется сортировать по длине
Глобальные объекты: window → глобальный объект в браузере. global → глобальный объект в Node.js (в браузере его нет). globalThis → единый стандарт ES2020, работает и в браузерах, и в Node.js. consоle - это свойство глобального объекта
Сокращение записи метода
const objectA = {a: 10, b: function () {console.log("тело");}}; // метод (полная запись)
objectA.b(); // → "тело"
const objectA = {a: 10, b() {console.log("тело");}};}; // метод (сокращённая запись)
objectA.b(); // → "тело"
JSON - формат обмена данных
let rJSON = '{"id": 1, "ti": 2}'; // это строка JSON
let rJS = JSON.parse(rJSON); // метод конвертации данных JSON в объект JS
console.log(rJS); // → { id: 1, ti: 2 } (объект JS)
let rJSON = JSON.stringify(rJS); // метод конвертации объекта JS в данные JSON
console.log(rJSON); // → '{"id":1,"ti":2}' (строка JSON)
Копирование:
Копия по ссылке (изменения отражаются в оригинале)
const pe = { a: 10, b: { x: 1, y: 2 } }; // исходный объект
const peRef = pe; // копия по ссылке
peRef.a = 20; // меняем свойство a через ссылку
console.log(pe.a); // вывод значения a из оригинала
// → 20 (оригинал изменился)
Поверхностная копия (вложенный объект всё ещё общая ссылка)
Копирует все свойства верхнего уровня объекта; примитивы (string, number, boolean, null, undefined, symbol, bigint) - копируется по значению; объекты, массив или функция - копируется ссылка на тот же самый объект/массив/функцию. Изменения вложенных объектов «объекты, массив или функция» в копии повлияют на оригинал.
const pe = { a: 10, b: { x: 1, y: 2 } }; // исходный объект
const peShallow1 = Object.assign({}, pe); // поверхностная копия 1 (старый способ)
const peShallow2 = { ...pe }; // поверхностная копия 2 (современный и более читаемый синтаксис)
peShallow1.a = 30; // меняем a в первой поверхностной копии
peShallow2.a = 40; // меняем a во второй поверхностной копии
peShallow1.b.x = 99; // меняем вложенный объект
Глубокая копия (изменения в копии не затрагивают оригинал.) Копируются все уровни вложенности, включая вложенные объекты и массивы.
const pe = { a: 10, b: { x: 1, y: 2 } }; // исходный объект
const peDeep = JSON.parse(JSON.stringify(pe)); // Глубокая копия (deep copy)
peDeep.b.x = 555; // меняем вложенный объект в глубокой копии
console.log(pe.b.x); // → 99 (оригинал не изменился)
Внутри функции можно делать копии.
Функции:
Функции могут быть: именованными, присвоенными переменной, анонимными, стрелочными, методами объектов.
Два способа создать функцию:
Функциональное объявление (Function Declaration)
Работает везде в коде (даже до строки, где она объявлена). Интерпретатор поднимает (hoists) её вверх во время запуска. Используется для Основных функций, Простая функция, часто вызывается
- Функциональное выражение (Function Expression)
Это просто переменная, в которую мы положили функцию. Не работает до объявления, потому что переменная ещё не инициализирована. Можно делать анонимные функции (без имени). Используется для Колбэков, обработчиков, замыканий, стрелочная функция, вложенных
Внутри функции мутировать внешний объект нерекоменовано
let a = 3;
let d = 2;
// Именованная функция
function sum(a, d) {
const c = a + d;
console.log(c);
return c; // если нет return, функция вернёт undefined
}
sum(a, d); // → 5
console.dir(sum); // показывает структуру функции в браузере
console.log(sum.toString());// показывает тело функции как строку
// Функция, присвоенная переменной
const multiply = function(x, y) {
return x * y;
};
console.log(multiply(2,3)); // → 6
// Анонимная функция (без имени), как аргумент
[1,2,3].forEach(function(item) {
console.log(item); // выводит каждый элемент массива
});
// Функция-стрелка
const divide = (x, y) => x / y; // не имеет имени
console.log(divide(10,2)); // → 5
// Функция как значение свойства объекта (метод)
const obj = {
greet() { console.log("Привет"); }
};
obj.greet(); // → "Привет"
console.dir(sum); // показывает структуру функции в браузере
console.log(sum.toString()); // показывает тело функции как строку
function makeCounter() {}
const counter = makeCounter(); // присвоение переменной функции, переменой сохраняется функция
console.log(counter()); // вызов функции через переменную