Перейти к основному содержимому

Работа с объектами и прототипами

Разработчику Архитектору
Сначала — общие понятия (раздел 4 "Код")

Если ООП для вас новое или вы учите JavaScript с нуля, сначала пройдите материалы без привязки к синтаксису: парадигмы и уровни абстракции, затем ООП — о разделезачем объекты, введение, абстракция, инкапсуляция, наследование, полиморфизм.

Ниже — объекты, прототипы и классы ES6 в JavaScript.

Теория и модель JavaScript

Понятие ООПКак выражено в JavaScript
Объектлитералы {}, ссылочная семантика
Классclass ES6 — синтаксический сахар над прототипами
Наследованиецепочка [[Prototype]], extends
Инкапсуляцияполя класса #private, замыкания, модули ES
Полиморфизмduck typing; один интерфейс — разные объекты
Сообщениявызов метода; близко к модели Smalltalk

Определения — раздел 4-08-oop.


Работа с объектами

Базовый синтаксис объектов

Создание литерала, доступ через точечную и скобочную нотацию, изменение полей, деструктуризация и методы с this — в главе Типы данных — объект. Ниже — прототипы, классы ES6 и ООП в JavaScript.

Классы в живом интерфейсе

Синтаксис class, constructor и методы экземпляра удобнее всего отработать на виджете с DOM: промо-карусель с init() и автопрокруткой — в главе Виджеты интерфейса на ванильном JavaScript (разметка — в CSS, промо-карусель).

Интерактивная схема — класс и объект (псевдокод; в JS классы ES6 — сахар над прототипами). Полный разбор принципов: ООП в разделе "Код и разработка".

КЛАСС Кот
поля: имя, возраст
метод мяукнуть()
КОНЕЦ

объект barsik := новый Кот(имя="Барсик", возраст=3)
barsik.мяукнуть()

Разбор:

  • Это псевдокод, который иллюстрирует базовую модель ООП: сначала описывается шаблон сущности (класс), затем создаётся конкретный экземпляр (объект).
  • Блок поля — имя, возраст задаёт состояние объекта — данные, которые хранятся у каждого экземпляра отдельно.
  • Строка метод мяукнуть() показывает поведение объекта: методы связывают действия с конкретным типом сущности.
  • новый Кот(...) демонстрирует инстанцирование, где в объект передаются начальные значения полей.
  • Вызов barsik.мяукнуть() показывает точечную нотацию доступа к методам экземпляра.
  • Такая схема помогает понять, как от абстракции перейти к реальному объекту в коде JavaScript.

Play ITЗагрузка интерактивного демо…

JavaScript — прототипно-ориентированный язык. Классы (ES6+) — это синтаксический сахар над прототипами. Всё, включая функции и массивы, — объекты.

Главное отличие от Java/C++/C#: нет классов в классическом понимании. Наследование — через цепочку прототипов.

Современный синтаксис (ES6+ class):

Код ITЗагрузка примера кода…

Разбор:

  • class Warrior объявляет класс с полями, методами, геттерами и статическими членами, то есть полный современный ES6+ синтаксис.
  • static count и static getCount() относятся к самому классу, а не к экземплярам; это удобно для общей статистики.
  • constructor(name, level = 1) выполняется при new и инициализирует состояние через this.
  • Геттер get damage() вычисляет значение как свойство, поэтому вызывается без скобок и выглядит как обычное поле.
  • class Knight extends Warrior включает наследование, а super(...) и super.attack(...) дают доступ к логике родителя.
  • Переопределение attack демонстрирует полиморфизм: дочерний класс меняет поведение, сохраняя общий контракт метода.
  • Финальный блок использования показывает жизненный цикл: создание объектов, вызов методов и чтение геттера.

Прототипная сущность:

Код ITЗагрузка примера кода…

Разбор:

  • Пример показывает "классическую" прототипную модель до class: функции-конструкторы и ручную работу с prototype.
  • WarriorOld задаёт поля через this, а метод attack добавляется в WarriorOld.prototype, чтобы не копировать функцию в каждый объект.
  • В KnightOld вызов WarriorOld.call(this, name) имитирует вызов родительского конструктора и переносит базовую инициализацию.
  • KnightOld.prototype = Object.create(WarriorOld.prototype) строит корректную цепочку прототипов для наследования методов.
  • Восстановление constructor важно для корректной рефлексии и диагностики типа объекта.
  • Вызов w.attack() подтверждает, что метод найден по прототипной цепочке, хотя в самом объекте w он явно не объявлен.

ES6 class делает ТОЧНО ТАК ЖЕ, просто красивее.

Прототипная цепочка (как работает "наследование"):

const arr = [1, 2, 3];
console.log(arr.__proto__ === Array.prototype); // true
console.log(Array.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

// Поиск свойства: arr -> Array.prototype -> Object.prototype -> null
arr.push(4); // нашли в Array.prototype
arr.toString(); // нашли в Object.prototype (переопределён в Array)

Получается, классов тут нет. Есть объекты, которые ссылаются на другие объекты (прототипы).

В ES2022 добавили приватные поля:

Код ITЗагрузка примера кода…

Но!

Главное отличие - объекты без классов.

Код ITЗагрузка примера кода…

Это замыкания + фабрики вместо классов. Без this, без new, с реальной приватностью.

JavaScript не классический ООП-язык. Он прототипный. И классы ES6 — это не то же самое, что классы в Java.

Философия JS: объекты напрямую наследуют от других объектов. Классы — просто удобная обёртка.


this

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

Когда говорит Петя, то "я" в его речи говорит именно о нём. Когда говорит Маша, то "я" в её речи - о ней.

В программировании так же - если сейчас выполняется код внутри объекта, то this, подобно "я", будет ссылкой на объект, который вызывает текущий код в данный момент.

В глобальной области — this это объект window (браузер):

console.log(this); // Window { ... }

function showThis() {
console.log(this); // Window (в нестрогом режиме)
}

showThis(); // Window

А вот внутри метода объекта this будет означать сам объект:

const user = {
name: "Alice",
greet: function() {
console.log(this.name); // this = user
console.log(this); // { name: "Alice", greet: f }
}
};

user.greet(); // "Alice"

В конструкторе/классе this будет означать новый создаваемый объект:

Код ITЗагрузка примера кода…

А в стрелочных функциях this берётся из родительской области:

Код ITЗагрузка примера кода…

this определяется в момент ВЫЗОВА функции, а не в момент её создания. А стрелочные функции — исключение, они берут this из места своего создания.


Пример класса в JS

Код ITЗагрузка примера кода…

Ключевое слово class определяет новый класс. Внутри фигурных скобок размещаются свойства и методы класса.

Метод constructor вызывается автоматически при создании нового объекта с помощью оператора new. В конструкторе инициализируются начальные значения свойств объекта.

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

Метод get damage() представляет собой геттер — специальный метод, который вычисляет значение свойства каждый раз при обращении к нему. Геттер позволяет динамически рассчитывать урон на основе текущих характеристик персонажа.

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

Оператор new создаёт новый экземпляр класса. После создания объекта можно изменять значения его свойств, присваивая новые значения напрямую.

Для вызова метода объекта используется точечная нотация — имя объекта, точка, имя метода и круглые скобки с аргументами.


Объекты и классы

В JavaScript, с появлением ES6 (2015) используется "синтаксический сахар" над прототипным наследованием – классы. Это позволяет писать код в более привычном ООП-стиле. Благодаря классам, может быть создан объект (некоторые объекты уже создаются – элементы DOM), и можно получить доступ к свойствам или методам класса. К примеру, можно вызвать класс.метод() и сразу вызывать уже существующие стандартные возможности, а также создавать свои.

Объект JavaScript может быть пользовательским (со своими свойствами и методами) или объектом DOM.

Их можно расширять при помощи миксинов (путем объединения свойств и методов из одного или нескольких исходных объектов). Микс - смешивать, смешивают поведение нескольких в один объект.

image-7.png

К примеру, так выглядит базовый объект:

// Базовый объект
const Объект = {
имя: "Основной объект",
метод() {
console.log("Это метод основного объекта.");
}
};

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

Вышеприведенный пример называется простым созданием объекта (литерал):

let obj = {
key: "value",
anotherKey: "AnotherValue"
};
<имя объекта> = {
<ключ>: <значение>,
<ключ>: <значение>,
...
};

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

<объект>.<свойство>

Это более сложный тип данных, который можно записать в переменную и придать ему свойства в виде "ключ: “значение”". Это может быть, к примеру, пользователь с присущими ему именем, Email и возрастом:

let user = {
name: "Тимур",
email: "timur@mail.com",
age: 30
};

Почему это называется простым созданием? Потому что есть более сложное - с использованим классов или через функцию конструктор.

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

function Объект(значение) {
this.ключ = значение;
this.другойКлюч = "значение по умолчанию";
}

let obj1 = new Объект("привет");
let obj2 = new Объект("мир");

console.log(obj1); // { ключ: "привет", другойКлюч: "значение по умолчанию" }

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

Объекты нужны для создания комплексного набора данных с разными типами, и при работе с JS в крупных системах, как правило, работа с объектами неизбежна. Важное отличие от примитивов в том, что они работают ссылочно, благодаря чему переменная лишь ссылается на объект. Ссылаться на объект user могут несколько переменных, что позволяет не копировать все значение целиком - память будет использоваться как для одного набора данных. Но давайте пока не будем в это погружаться. Это станет понятно позднее.

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

let собака = {
имя: "Тарзан",
лает: function() {
console.log(this.имя + " говорит: Гав-гав!");
}
};

Здесь "лает" является методом объекта "собака". И "this" — это ключевое слово, которое ссылается на сам объект "собака". В дальнейшем мы просто можем вызывать метод через точку:

собака.лает(); // "Тарзан говорит: Гав-гав!"

Вызов метода объекта:

<объект>.<метод>(<аргументы>)

В ES6 появился и более удобный способ:

let собака = {
имя: "Тарзан",
лает() {
console.log(this.имя + " говорит: Гав-гав!");
},
ест(еда) {
console.log(this.имя + " ест " + еда);
}
};

собака.лает(); // Гав-гав!
собака.ест("корм"); // Тарзан ест корм

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

let кот = {
имя: "Барсик"
};

// Добавляем метод позже
кот.мяукает = function() {
console.log(this.имя + " говорит: Мяу!");
};

кот.мяукает(); // "Барсик говорит: Мяу!"

Добавление нового свойства или метода к существующему объекту:

<объект>.<новое свойство> = <значение>;
<объект>.<новый метод> = function(<параметры>) { ... };

this — это ссылка на объект, который вызывает функцию. Это называется контекст выполнения - this определяется в момент вызова функции, а не при её создании и зависит от способа вызова функции.

Если вызывать this в методе объекта, то this = сам объект. В больших проектах работа с объектами позволит использовать автодополнение в браузере или IDE, когда можно будет указать "кот." и IDE выведет доступные свойства и методы.

Ранее мы упоминали, что существует деструктивное присваивание — это может быть применено и к объектам.

Пример:

let user = { name: "Боб", age: 30 };

let { name, age } = user;

console.log(name); // "Боб"
console.log(age); // 30

prototype — это механизм наследования в JavaScript, основанный на цепочке прототипов (prototype chain). Каждая функция в JS имеет свойство prototype, которое используется, когда функция используется как конструктор (с new).

prototype — это свойство функции-конструктора.

__proto__ — это свойство объекта, указывающее на его прототип (устаревшее, но работает; современный аналог — Object.getPrototypeOf()).

superclass — это родительский класс, от которого наследуется другой класс (дочерний, или подкласс).

Этот термин чаще используется в контексте классов (ES6+) и наследования через extends.

Объявление класса:

class <ИмяКласса> {
constructor(<параметры>) {
this.<свойство> = <значение>;
...
}

<метод>(<параметры>) {
...
}
}

Создание экземпляра класса:

<экземпляр> = new <ИмяКласса>(<аргументы>);

Наследование класса:

class <ДочернийКласс> extends <РодительскийКласс> {
constructor(<параметры>) {
super(<параметры>);
...
}

<метод>(<параметры>) {
...
}
}

Использование this внутри метода:

this.<свойство>
this.<метод>(<аргументы>)

Деструктуризация объекта — извлечение свойств в переменные; подробнее в типах данных — объект:

const { <свойство1>, <свойство2>, ... } = <объект>;

Создание объекта через функцию-конструктор:

function <ИмяКонструктора>(<параметры>) {
this.<свойство> = <значение>;
...
}

<экземпляр> = new <ИмяКонструктора>(<аргументы>);

Добавление метода в прототип конструктора:

<ИмяКонструктора>.prototype.<метод> = function(<параметры>) {
...
};

Получение прототипа объекта:

Object.getPrototypeOf(<объект>)

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

<объект>.hasOwnProperty(<свойство>)

Перебор собственных перечисляемых свойств объекта:

for (let <ключ> in <объект>) {
if (<объект>.hasOwnProperty(<ключ>)) {
...
}
}

Простые примеры прототипов

Представим, что у нас есть объект.

let animal = {
eats: true,
walk() {
console.log("Животное идёт");
}
};

Это классический пример - животное (animal). У него могут быть наследники, к примеру, кролик:

let rabbit = {
jumps: true,
__proto__: animal // устанавливаем прототип
};

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

Теперь мы можем получать все, что есть у родителя:

console.log(rabbit.jumps); // true (своё свойство)
console.log(rabbit.eats); // true (взято из прототипа animal)
rabbit.walk(); // "Животное идёт" (метод из прототипа)

Можно добавить свойство уже после создания объекта:

let animal = { eats: true };
let rabbit = { jumps: true };

rabbit.__proto__ = animal;

for (let prop in rabbit) {
console.log(prop); // "jumps", потом "eats"
}

Цикл for...in, кстати, проходит по всем перечисляемым свойствам, включая те, что пришли по цепочке прототипов.

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

Код ITЗагрузка примера кода…

Метод hasOwnProperty нужен, чтобы отфильтровать унаследованные свойства из прототипа. Он возвращает true, если свойство принадлежит непосредственно объекту, а не его прототипу.

for (let prop in rabbit) {
if (rabbit.hasOwnProperty(prop)) { // проверяет: своё ли свойство?
console.log(prop); // только "jumps"
}
}

Таким образом можно отличать "своё" от чужого.

Часто нужны только собственные поля объекта, а не все подряд от предков. Например, при копировании, сериализации в JSON или валидации — не хочется тащить мусор из прототипа.

Можно переопределять методы (overriding):

Код ITЗагрузка примера кода…

Пример с вызовом родительского метода:

Код ITЗагрузка примера кода…

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

Код ITЗагрузка примера кода…

Можно переопределить что угодно — методы, свойства. Оригинал в прототипе при этом не меняется. Это называется shadowing (затенение).


Получение свойств и методов объекта

В JavaScript очень часто приходится работать с объектами, чья структура неочевидна — это может быть объект из API, библиотеки, фреймворка (React, Vue, Express), или даже this в сложной цепочке вызовов. И на практике сталкиваться можно с непониманием того, что есть у объекта. Узнать, какие свойства или методы есть у объекта, можно несколькими способами.

  1. Консоль. Можно открыть консоль в инструментах разработчика (DevTools, F12), поставить точку останова на нужной строке и запустить выполнение кода. После этого, в консоли можно просто написать this и поставить точку - после точки будет отображено всё возможное - так работает автодополнение:

image-8.png

  1. Дерево объекта. Также можно в браузере написать console.log(myObject); - после чего в консоли браузера увидим интерактивное дерево объекта - по нему можно кликать, раскрывать свойства, смотреть методы.

image-9.png

А если написать console.dir(myObject) — это покажет только свойства и методы, без лишней информации. Можете открыть любой сайт и попробовать протестировать, написав console.log(this) или console.dir(this). Если навести мышкой на объект - подсказка покажет тип и структуру.

Если при поиске объекта, к примеру myObject.test() получаем ошибку "Uncaught TypeError: myObject.test is not a function", значит такой функции нет. А если напишем myObject.test, но такого свойства нет, то получим undefined - "неопределенно".

  1. Можно использовать методы для перечисления свойств, что позволит программно узнать, что внутри объекта:
    • Object.keys(obj) вернёт массив собственных перечисляемых свойств ([‘name’, ‘age’]);
    • Object.values(obj) вернёт массив значений свойств ([‘Тимур’, ‘30’]);
    • Object.entries(obj) вернет свойства целиком ([‘name’, ‘Тимур’], [‘age’, ‘30’]);
    • for…in позволит перебирать свойства, к примеру:
for (let key in user) {
console.log(key, user[key]);
}
  • Object.getOwnPropertyNames(obj) покажет все собственные свойства, включая неперечисляемые;
  • Reflect.ownKeys(obj) покажет все собственные ключи, включая символы (Symbol) и неперечисляемые.
  1. VS Code и другие IDE. Если объект имеет типизацию (например, JSDoc, TypeScript или встроен в JS (базовый объект), то VS Code покажет подсказки при наведении и автодополнении. К примеру:
const arr = [1, 2, 3];
arr. // → сразу выпадает список методов: push, pop, map, filter и т.д.

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


Миксин

Мы можем создать миксины:

// Миксин 1
const Миксин1 = {
миксин1Метод() {
console.log("Это метод из Миксина 1.");
}
};
// Миксин 2
const Миксин2 = {
миксин2Метод() {
console.log("Это метод из Миксина 2.");
}
};

Теперь это два "дополнительных объекта", которые имеют свои методы миксин1Метод() и миксин2Метод().

После этого мы можем либо использовать Object.assign, чтобы скопировать свойства и методы из Миксин1 и Миксин2 в Объект:

// Применяем миксины напрямую через Object.assign
Object.assign(Объект, Миксин1, Миксин2);

// Используем расширенный объект
Объект.метод(); // Это метод основного объекта.
Объект.миксин1Метод(); // Это метод из Миксина 1.
Объект.миксин2Метод(); // Это метод из Миксина 2.

…либо использовать функцию смешивания:

// Функция для смешивания (применения миксинов)
function применитьМиксины(целевойОбъект, ...миксины) {
миксины.forEach(миксин => {
Object.assign(целевойОбъект, миксин);
});
}
// Применяем миксины к объекту
применитьМиксины(Объект, Миксин1, Миксин2);

Применение миксина (копирование свойств из одного объекта в другой):

Object.assign(<целевой объект>, <источник1>, <источник2>, ...);

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

// Применяем миксины к объектам
применитьМиксины(Объект1, Миксин1, Миксин2);
применитьМиксины(Объект2, Миксин1);
// Используем расширенные объекты
Объект1.метод(); // Это метод первого объекта.
Объект1.миксин1Метод(); // Это метод из Миксина 1.
Объект1.миксин2Метод(); // Это метод из Миксина 2.
Объект2.метод(); // Это метод второго объекта.
Объект2.миксин1Метод(); // Это метод из Миксина 1.
// Объект2.миксин2Метод(); // Ошибка: метод миксин2Метод не определён, так как Миксин2 не был применён.

Базовые операции с объектами и классами

Объявление класса:

class Person {
// Конструктор (вызывается при создании объекта)
constructor(name, age) {
this.name = name; // Свойство
this.age = age;
}

// Метод
greet() {
return `Привет, я ${this.name}!`;
}
}

Создание объекта (экземпляра класса):

const person = new Person('Том', 25);
console.log(person.greet()); // "Привет, я Том!"

Свойства – это переменные, принадлежащие объекту/классу.

Публичные свойства доступны извне класса:

class Car {
constructor(brand) {
this.brand = brand; // Публичное свойство
}
}

const myCar = new Car('Toyota');
console.log(myCar.brand); // "Toyota"

Интерактивная схема — инкапсуляция (псевдокод). Подробнее: Инкапсуляция.

Play ITЗагрузка интерактивного демо…

Приватные свойства (с префиксом #) доступны только внутри класса:

class User {
#password; // Приватное свойство

constructor(login, password) {
this.login = login;
this.#password = password;
}
}

const user = new User('admin', '12345');
console.log(user.#password); // Ошибка!

Статические свойства (static) принадлежат классу, а не экземплярам:

class MathUtils {
static PI = 3.14; // Статическое свойство
}

console.log(MathUtils.PI); // 3.14

Методы – это функции, принадлежащие классу/объекту.

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

Пример – класс для работы с API:

Код ITЗагрузка примера кода…


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

Литералы объектов

Литерал объекта — это выражение, создающее объект с указанными свойствами и методами:

const user = {
name: "Алексей",
age: 28,
greet() {
return `Привет, меня зовут ${this.name}`;
}
};

Конструкторы через функции

Функция-конструктор создаёт объекты с заданной структурой:

function User(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
return `Привет, меня зовут ${this.name}`;
};
}

const user1 = new User("Мария", 25);
const user2 = new User("Иван", 30);

Object.create()

Метод Object.create() создаёт новый объект с указанным прототипом:

const parent = {
greet() {
return `Привет от ${this.name}`;
}
};

const child = Object.create(parent);
child.name = "Дочерний объект";
console.log(child.greet()); // "Привет от Дочерний объект"

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

Геттеры и сеттеры

Геттеры и сеттеры позволяют контролировать доступ к свойствам:

Код ITЗагрузка примера кода…


Дескрипторы свойств

Дескрипторы описывают поведение свойств объекта:

const obj = {};

Object.defineProperty(obj, 'name', {
value: 'Тест',
writable: false, // нельзя изменить
enumerable: true, // видно в циклах
configurable: false // нельзя удалить или изменить дескриптор
});

obj.name = 'Новое'; // Не сработает
console.log(obj.name); // "Тест"

Полный пример с геттером и сеттером через дескриптор:

Код ITЗагрузка примера кода…


Прототипное наследование

Цепочка прототипов

Каждый объект имеет внутреннее свойство [[Prototype]], ссылающееся на другой объект — прототип. При обращении к свойству объекта, если его нет в самом объекте, поиск продолжается в прототипе:

const animal = {
eats: true,
walk() {
console.log("Животное ходит");
}
};

const rabbit = Object.create(animal);
rabbit.jumps = true;
rabbit.walk(); // "Животное ходит" — метод из прототипа

console.log(rabbit.eats); // true — свойство из прототипа
console.log(rabbit.jumps); // true — собственное свойство

Изменение прототипа

Современный способ изменения прототипа — Object.setPrototypeOf():

const parent = { parentProp: "родитель" };
const child = { childProp: "ребёнок" };

Object.setPrototypeOf(child, parent);
console.log(child.parentProp); // "родитель"

Проверка прототипа

Метод isPrototypeOf() проверяет, является ли объект прототипом другого:

const parent = {};
const child = Object.create(parent);

console.log(parent.isPrototypeOf(child)); // true
console.log(Object.prototype.isPrototypeOf(child)); // true

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

Object.keys(), values(), entries()

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

const user = {
name: "Олег",
age: 30,
city: "Москва"
};

console.log(Object.keys(user)); // ["name", "age", "city"]
console.log(Object.values(user)); // ["Олег", 30, "Москва"]
console.log(Object.entries(user)); // [["name","Олег"],["age",30],["city","Москва"]]

Object.assign()

Копирует свойства из одного или нескольких источников в целевой объект:

const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
console.log(target); // { a: 1, b: 2, c: 3 }

Глубокое копирование требует рекурсивного подхода:

Код ITЗагрузка примера кода…


Object.defineProperty() и Object.defineProperties()

Определяют или изменяют свойства объекта с точным контролем:

Код ITЗагрузка примера кода…


Object.freeze(), seal(), preventExtensions()

Эти методы ограничивают изменение объекта:

Код ITЗагрузка примера кода…


Object.hasOwnProperty()

Проверяет, является ли свойство собственным (не унаследованным):

const parent = { parentProp: "родитель" };
const child = Object.create(parent);
child.childProp = "ребёнок";

console.log(child.hasOwnProperty("childProp")); // true
console.log(child.hasOwnProperty("parentProp")); // false
console.log("parentProp" in child); // true — проверяет включая прототипы

Function как конструктор

Функция в JavaScript может выступать в роли конструктора при вызове с оператором new:

function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
return `Привет, меня зовут ${this.name}`;
};
}

const person = new Person("Сергей", 35);
console.log(person.name); // "Сергей"
console.log(person.greet()); // "Привет, меня зовут Сергей"

Свойство prototype функции-конструктора становится прототипом созданных объектов:

function Car(brand) {
this.brand = brand;
}

Car.prototype.start = function() {
console.log(`${this.brand} заводится`);
};

const myCar = new Car("Toyota");
myCar.start(); // "Toyota заводится"

Синтаксис классов

Базовый класс

Класс — это шаблон для создания объектов:

Код ITЗагрузка примера кода…


Конструктор

Конструктор инициализирует новый объект:

Код ITЗагрузка примера кода…


Наследование через extends

Интерактивная схема — наследование (псевдокод). Подробнее: Наследование.

Play ITЗагрузка интерактивного демо…

Интерактивная схема — полиморфизм (псевдокод). Подробнее: Полиморфизм.

Play ITЗагрузка интерактивного демо…

Ключевое слово extends создаёт дочерний класс:

Код ITЗагрузка примера кода…


Методы super

Ключевое слово super обращается к методам родительского класса:

Код ITЗагрузка примера кода…

В конструкторе дочернего класса super() должен вызываться до использования this:

class Parent {
constructor(name) {
this.name = name;
}
}

class Child extends Parent {
constructor(name, age) {
super(name); // Обязательно первым
this.age = age;
}
}

Статические методы и поля

Статические члены принадлежат классу, а не экземплярам:

Код ITЗагрузка примера кода…


Приватные поля и методы

Приватные члены доступны только внутри класса:

Код ITЗагрузка примера кода…


Статические блоки инициализации

Статические блоки выполняют сложную инициализацию статических полей:

Код ITЗагрузка примера кода…


Практические примеры

Построение иерархии классов

Код ITЗагрузка примера кода…


Фабрика объектов

Код ITЗагрузка примера кода…


Базовые объекты

Базовые встроенные объекты

Базовые встроенные объекты

JavaScript предоставляет стандартные объекты-конструкторы для работы с разными типами данных:

ОбъектОписаниеПример использования
ArrayРабота с массивами[1, 2, 3].map(x => x * 2)
BooleanЛогические значенияnew Boolean(true)
MathМатематические операцииMath.PI, Math.random()
NumberЧисла и методыNumber.parseInt("42")
StringСтроки и методы"Hello".toUpperCase()
GlobalГлобальные функцииisNaN(), eval()

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

globalThis

Глобальный объект globalThis обеспечивает единый способ доступа к глобальному объекту в разных средах выполнения JavaScript. В браузере глобальным объектом является window, в Node.js — global, а globalThis работает везде одинаково:

// В браузере
console.log(globalThis === window); // true

// В Node.js
console.log(globalThis === global); // true

// Универсальный доступ
globalThis.myGlobalVar = "Значение";
console.log(globalThis.myGlobalVar); // "Значение"

Infinity

Свойство Infinity представляет бесконечность — числовое значение, большее любого другого числа:

console.log(Infinity); // Infinity
console.log(10 / 0); // Infinity
console.log(Infinity + 1); // Infinity
console.log(Infinity * 2); // Infinity
console.log(Infinity - Infinity); // NaN

// Проверка на бесконечность
console.log(isFinite(Infinity)); // false
console.log(isFinite(100)); // true
console.log(Number.isFinite(Infinity)); // false

Отрицательная бесконечность:

console.log(-Infinity); // -Infinity
console.log(-10 / 0); // -Infinity

NaN

NaN (Not-a-Number) представляет результат неопределённой или некорректной математической операции:

console.log(NaN); // NaN
console.log(0 / 0); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(parseInt("текст")); // NaN
console.log("строка" * 5); // NaN

Особенность NaN — он не равен ничему, включая самого себя:

console.log(NaN === NaN); // false
console.log(NaN == NaN); // false

Проверка на NaN:

console.log(isNaN(NaN)); // true
console.log(isNaN("текст")); // true — преобразует в число сначала
console.log(isNaN(123)); // false

// Более точная проверка
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("текст")); // false — не преобразует
console.log(Number.isNaN(123)); // false

undefined

undefined означает, что переменная объявлена, но не инициализирована, или свойство объекта отсутствует:

let x;
console.log(x); // undefined
console.log(typeof x); // "undefined"

const obj = {};
console.log(obj.nonExistentProperty); // undefined

function noReturn() {}
console.log(noReturn()); // undefined

Проверка на undefined:

let value;

if (value === undefined) {
console.log("Значение не определено");
}

// Безопасная проверка
if (typeof value === "undefined") {
console.log("Переменная не определена");
}

Глобальные функции

eval()

Функция eval() выполняет строку как код JavaScript:

const code = "console.log('Привет, мир!')";
eval(code); // "Привет, мир!"

const result = eval("2 + 2 * 3");
console.log(result); // 8

const x = 10;
const y = 20;
console.log(eval("x + y")); // 30

Опасности использования eval():

  • Выполнение непроверенного кода создаёт уязвимости
  • Замедляет выполнение программы
  • Нарушает безопасность приложения
  • Затрудняет отладку кода

Безопасные альтернативы:

// Вместо eval для вычисления математических выражений
const expression = "2 + 2 * 3";
const result = Function('"use strict";return (' + expression + ')')();
console.log(result); // 8

// Для парсинга JSON
const jsonString = '{"name":"Иван","age":30}';
const obj = JSON.parse(jsonString);
console.log(obj.name); // "Иван"

isFinite()

Функция isFinite() проверяет, является ли значение конечным числом:

console.log(isFinite(123)); // true
console.log(isFinite(-123)); // true
console.log(isFinite(0)); // true
console.log(isFinite(Infinity)); // false
console.log(isFinite(-Infinity)); // false
console.log(isFinite(NaN)); // false

// Строки преобразуются в числа
console.log(isFinite("123")); // true
console.log(isFinite("12.5")); // true
console.log(isFinite("текст")); // false
console.log(isFinite("")); // true (пустая строка → 0)

Более строгая проверка через Number.isFinite():

console.log(Number.isFinite(123)); // true
console.log(Number.isFinite("123")); // false — не преобразует строку
console.log(Number.isFinite(NaN)); // false

isNaN()

Функция isNaN() проверяет, является ли значение NaN:

console.log(isNaN(NaN)); // true
console.log(isNaN("текст")); // true — "текст" → NaN
console.log(isNaN(123)); // false
console.log(isNaN("123")); // false — "123" → 123
console.log(isNaN("")); // false — пустая строка → 0
console.log(isNaN(" ")); // false — пробел → 0

Разница между isNaN() и Number.isNaN():

console.log(isNaN("привет")); // true
console.log(Number.isNaN("привет")); // false — не преобразует

console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true

console.log(isNaN(undefined)); // true
console.log(Number.isNaN(undefined)); // false

parseInt()

Функция parseInt() преобразует строку в целое число:

console.log(parseInt("42")); // 42
console.log(parseInt("42px")); // 42
console.log(parseInt("10.5")); // 10 — дробная часть отбрасывается
console.log(parseInt("0xFF")); // 255 — шестнадцатеричное
console.log(parseInt("10", 2)); // 2 — двоичная система
console.log(parseInt("10", 8)); // 8 — восьмеричная система
console.log(parseInt("10", 16)); // 16 — шестнадцатеричная система

// Обработка некорректных значений
console.log(parseInt("текст")); // NaN
console.log(parseInt("")); // NaN
console.log(parseInt(" 42 ")); // 42 — пробелы игнорируются

Явное указание системы счисления:

console.log(parseInt("10", 10)); // 10
console.log(parseInt("FF", 16)); // 255
console.log(parseInt("77", 8)); // 63
console.log(parseInt("1010", 2)); // 10

parseFloat()

Функция parseFloat() преобразует строку в число с плавающей точкой:

console.log(parseFloat("3.14")); // 3.14
console.log(parseFloat("3.14px")); // 3.14
console.log(parseFloat("10")); // 10
console.log(parseFloat("10.00")); // 10
console.log(parseFloat("2.5e3")); // 2500 — экспоненциальная запись
console.log(parseFloat("Infinity")); // Infinity

// Обработка некорректных значений
console.log(parseFloat("текст")); // NaN
console.log(parseFloat("")); // NaN
console.log(parseFloat(" 3.14 ")); // 3.14

Разница между parseInt() и parseFloat():

console.log(parseInt("10.99")); // 10 — только целая часть
console.log(parseFloat("10.99")); // 10.99 — сохраняет дробную часть

console.log(parseInt("3.5e2")); // 3
console.log(parseFloat("3.5e2")); // 350

Кодирование и декодирование URI

Функции для работы с URL и URI:


encodeURI()

Кодирует полный URI, сохраняя разделители:

const uri = "https://сайт.рф/путь?параметр=значение с пробелами";
console.log(encodeURI(uri));
// "https://сайт.рф/путь?параметр=значение%20с%20пробелами"

// Сохраняет разделители URI
console.log(encodeURI("https://example.com/путь/страница"));
// "https://example.com/%D0%BF%D1%83%D1%82%D1%8C/%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0"

encodeURIComponent()

Кодирует компонент URI, включая разделители:

Код ITЗагрузка примера кода…


decodeURI()

Декодирует полный URI:

const encoded = "https://сайт.рф/путь?параметр=значение%20с%20пробелами";
console.log(decodeURI(encoded));
// "https://сайт.рф/путь?параметр=значение с пробелами"

decodeURIComponent()

Декодирует компонент URI:

Код ITЗагрузка примера кода…

Разница между encodeURI() и encodeURIComponent():

const url = "https://example.com/путь?параметр=значение с пробелами";

console.log(encodeURI(url));
// "https://example.com/%D0%BF%D1%83%D1%82%D1%8C?параметр=значение%20с%20пробелами"
// Символы ? и = сохраняются

console.log(encodeURIComponent(url));
// "https%3A%2F%2Fexample.com%2F%D0%BF%D1%83%D1%82%D1%8C%3F%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%3D%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%20%D1%81%20%D0%BF%D1%80%D0%BE%D0%B1%D0%B5%D0%BB%D0%B0%D0%BC%D0%B8"
// Все специальные символы кодируются

Устаревшие функции

escape() и unescape()

Эти функции считаются устаревшими и не должны использоваться в современном коде:

// Устаревший способ
const oldEncoded = escape("Привет мир!");
console.log(oldEncoded); // "%u041F%u0440%u0438%u0432%u0435%u0442%20%u043C%u0438%u0440%21"

const oldDecoded = unescape(oldEncoded);
console.log(oldDecoded); // "Привет мир!"

// Современная замена
const newEncoded = encodeURIComponent("Привет мир!");
console.log(newEncoded); // "%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80%21"

const newDecoded = decodeURIComponent(newEncoded);
console.log(newDecoded); // "Привет мир!"

Фундаментальные объекты

Boolean

Объект Boolean представляет логическое значение:

Код ITЗагрузка примера кода…

Разница между примитивом и объектом:

Код ITЗагрузка примера кода…


Symbol

Символы — это уникальные идентификаторы:

// Создание символов
const sym1 = Symbol();
const sym2 = Symbol("описание");
const sym3 = Symbol("описание");

console.log(sym1); // Symbol()
console.log(sym2); // Symbol(описание)
console.log(sym3); // Symbol(описание)

// Символы всегда уникальны
console.log(sym2 === sym3); // false
console.log(Symbol() === Symbol()); // false

Глобальный реестр символов:

const sym1 = Symbol.for("ключ");
const sym2 = Symbol.for("ключ");

console.log(sym1 === sym2); // true — один и тот же символ из реестра

console.log(Symbol.keyFor(sym1)); // "ключ"

Использование символов как ключей свойств:

Код ITЗагрузка примера кода…

Символы как константы:

Код ITЗагрузка примера кода…


Error и его подтипы

Объект Error представляет ошибку во время выполнения:

Код ITЗагрузка примера кода…


EvalError

Ошибка при работе с функцией eval():

try {
throw new EvalError("Ошибка при вычислении");
} catch (error) {
console.log(error.name); // "EvalError"
console.log(error.message); // "Ошибка при вычислении"
}

RangeError

Ошибка при выходе за пределы допустимого диапазона:

Код ITЗагрузка примера кода…


ReferenceError

Ошибка при обращении к несуществующей переменной:

Код ITЗагрузка примера кода…


SyntaxError

Ошибка синтаксиса в коде:

Код ITЗагрузка примера кода…


TypeError

Ошибка при применении операции к неподходящему типу:

Код ITЗагрузка примера кода…


URIError

Ошибка при работе с функциями кодирования URI:

Код ITЗагрузка примера кода…


AggregateError

Представляет несколько ошибок одновременно:

Код ITЗагрузка примера кода…


SuppressedError

Представляет ошибку, подавленную другой ошибкой (новый функционал):

Код ITЗагрузка примера кода…


InternalError (не стандартный)

Нестандартный объект ошибки, используемый в некоторых средах:

// Этот объект не является частью стандарта ECMAScript
// Может встречаться в старых версиях некоторых браузеров
try {
// Очень глубокая рекурсия
function recurse() {
recurse();
}
recurse();
} catch (error) {
console.log(error.name); // Может быть "InternalError" или "RangeError"
}

Практические примеры

Валидация данных с использованием глобальных функций

Код ITЗагрузка примера кода…


Создание кастомных ошибок

Код ITЗагрузка примера кода…


Особенности базовых объектов

Массив – основные методы:

МетодОписаниеПример
push() / pop()Добавить/удалить элемент в конецarr.push(4) → [1,2,3,4]
shift() / unshift()Удалить/добавить в началоarr.unshift(0) → [0,1,2,3]
slice()Копирует часть массиваarr.slice(1,3) → [2,3]
splice()Удаляет/заменяет элементыarr.splice(1,1) → [1,3]
map()Преобразует массив[1,2].map(x => x*2) → [2,4]
filter()Фильтрует элементы[1,2,3].filter(x => x>1) → [2,3]
reduce()Сворачивает массив в одно значение[1,2].reduce((a,b) => a+b) → 3
find()Находит первый подходящий элемент[1,2,3].find(x => x>1) → 2
sort()Сортирует массив[3,1].sort() → [1,3]
forEach(fn)Выполняет функцию для каждого элемента (ничего не возвращает)arr.forEach(el => console.log(el))
includes(value)Проверяет, есть ли элемент в массиве[1,2].includes(2) → true
indexOf(value)Возвращает индекс элемента или -1, если не найден[1,2,3].indexOf(2) → 1
some(fn)Проверяет, существует ли хотя бы один подходящий элемент[1,2].some(x => x > 1) → true
every(fn)Проверяет, все ли элементы соответствуют условию[2,3].every(x => x > 1) → true
join(separator)Преобразует массив в строку с указанным разделителем[1,2,3].join('-') → "1-2-3"
reverse()Разворачивает массив (мутирует оригинал)[1,2,3].reverse() → [3,2,1]
flat(n)Расплющивает вложенные массивы на n уровней[1, [2, [3]]].flat(2) → [1,2,3]
isArray()(статический)Проверяет, является ли значение массивомArray.isArray([1]) → true

Числа – основные методы и свойства:

Метод/ СвойствоОписаниеПример
Number.parseInt()Преобразует строку в целое числоparseInt("42") → 42
Number.parseFloat()Преобразует в дробное числоparseFloat("3.14") → 3.14
toFixed(n)Округляет до n знаков после запятой3.1415.toFixed(2) → "3.14"
toString()Преобразует число в строку42.toString() → "42"
Math.random()Случайное число от 0 до 1Math.random() → 0.123
Math.round()Округление до ближайшего целогоMath.round(3.6) → 4
Math.floor(x)Округляет вниз до целогоMath.floor(3.9) → 3
Math.ceil(x)Округляет вверх до целогоMath.ceil(3.1) → 4
Math.trunc(x)Убирает дробную часть, не округляяMath.trunc(3.9) → 3
Number.isNaN(value)Проверяет, является ли значение NaNNumber.isNaN(NaN) → true
Number.isFinite(value)Проверяет, является ли значение конечным числомNumber.isFinite(Infinity) → false
Number.isInteger(value)Проверяет, является ли число целымNumber.isInteger(42) → true
Math.pow(x, y)Возводит x в степень yMath.pow(2, 3) → 8
Math.sqrt(x)Квадратный корень из числаMath.sqrt(16) → 4
Math.min(...values)Находит минимальное числоMath.min(1, 2, 3) → 1
Math.max(...values)Находит максимальное числоMath.max(1, 2, 3) → 3
Number.MIN_VALUEМинимально возможное положительное числоNumber.MIN_VALUE → 5e-324
Number.MAX_VALUEМаксимально возможное числоNumber.MAX_VALUE → 1.7976...e+308

Строки – основные методы (разбор с примерами и шпаргалкой по группам — типы данных, методы строк):

МетодОписаниеПример
lengthДлина строки"hello".length → 5
toUpperCase()Преобразует в верхний регистр"Hi".toUpperCase() → "HI"
toLowerCase()Преобразует в нижний регистр"Hi".toLowerCase() → "hi"
includes()Проверяет наличие подстроки"hello".includes("ell") → true
split()Разделяет строку в массив"a,b,c".split(",") → ["a","b","c"]
trim()Удаляет пробелы с обоих концов" hi ".trim() → "hi"
replace()Заменяет подстроку"hi".replace("i", "ello") → "hello"
indexOf(substring)Возвращает индекс первого вхождения подстроки, или -1, если не найдено"hello".indexOf("e") → 1
lastIndexOf(substring)Возвращает индекс последнего вхождения подстроки"abacaba".lastIndexOf("a") → 6
slice(start, end?)Возвращает часть строки между начальным и конечным индексами (не включая конец)"hello".slice(1,4) → "ell"
substring(start, end?)То же, что и slice, но не поддерживает отрицательные значения"hello".substring(1,4) → "ell"
charAt(index)Возвращает символ по указанному индексу"hello".charAt(0) → "h"
startsWith(prefix)Проверяет, начинается ли строка с указанной подстроки"hello".startsWith("he") → true
endsWith(suffix)Проверяет, заканчивается ли строка указанной подстрокой"hello".endsWith("lo") → true
repeat(count)Повторяет строку заданное число раз"ha".repeat(3) → "hahaha"

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

ФункцияОписаниеПример
isNaN()Проверяет, является ли значение NaNisNaN("text") → true
parseInt()Аналог Number.parseInt()parseInt("42px") → 42
parseFloat()Аналог Number.parseFloat()parseFloat("3.14.15") → 3.14
eval()Выполняет строку как код (опасно!)eval("2+2") → 4
encodeURI()Кодирует URLencodeURI("https://сайт.рф") → "https://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84"

Работа с датами (Date)

Date – объект, который используется для работы с временем.

const now = new Date(); // Текущая дата

console.log(now.getFullYear()); // Год (2023)
console.log(now.getMonth()); // Месяц (0-11)
console.log(now.getDate()); // День месяца (1-31)
console.log(now.getHours()); // Часы (0-23)
console.log(now.toLocaleString()); // "12.01.2023, 14:30:00"

DOM

DOM (Document Object Model)

DOM – программное представление HTML-документа в виде дерева объектов. Объект Document представляет собой весь HTML-документ и является корневым узлом дерева DOM. Он предоставляет методы и свойства для взаимодействия с содержимым страницы — поиска элементов, создания новых узлов, изменения содержимого, управления стилями и многим другим.

Основные сущности DOM:

СущностьОписание
DocumentКорень DOM (весь документ)
ElementHTML-элемент
AttrАтрибут элемента
TextТекстовый узел
CommentКомментарий
DocumentFragmentЛегковесный "контейнер" для DOM
NodeБазовый класс для всех узлов
NodeListКоллекция узлов
NamedNodeMapКоллекция атрибутов элемента

Свойства Document:

СвойствоОписаниеПример
document.documentElement Ссылка на корневой элемент <html>document.documentElement.tagName → "HTML"
document.headСсылка на элемент <head>document.head.appendChild(myScript)
document.bodyСсылка на элемент <body>document.body.innerHTML = "<h1>Привет</h1>"
document.titleПолучает или устанавливает заголовок страницы (<title>)document.title = "Новая страница"
document.URLВозвращает полный URL текущего документаconsole.log(document.URL)
document.locationОбъект Location, содержащий информацию о текущем адресеdocument.location.href
document.linksКоллекция всех гиперссылок (<a>) на страницеdocument.links[0].href
document.imagesКоллекция всех изображений (<img>) на страницеdocument.images.length
document.formsКоллекция всех форм на страницеdocument.forms.loginForm

Методы поиска элементов:

МетодПримерВозвращает
getElementById()document.getElementById('app')Один Element
getElementsByClassName()document.getElementsByClassName('item')HTMLCollection
getElementsByTagName()document.getElementsByTagName('div')HTMLCollection
querySelector()document.querySelector('.btn')Первый подходящий Element
querySelectorAll()document.querySelectorAll('p')NodeList

Методы создания элементов:

  • createElement() – создаёт элемент;
  • createTextNode() –создаёт текстовый узел;
  • createComment() – создаёт комментарий;
  • createAttribute() – создаёт объект атрибута (реже setAttribute на элементе).

Обход и изменение дерева (узлы):

APIПримерДействие
appendChild(node)parent.appendChild(child)Добавить ребёнка в конец
insertBefore(new, ref)parent.insertBefore(li, first)Вставить перед ref
removeChild(node)parent.removeChild(child)Удалить дочерний узел
replaceChild(new, old)parent.replaceChild(newLi, oldLi)Заменить ребёнка
hasChildNodes()ul.hasChildNodes()Есть ли дочерние узлы
children / childNodesul.childrenЭлементы / все узлы (свойства)
firstElementChild, lastElementChildul.firstElementChildПервый / последний элемент-ребёнок
parentNodespan.parentNodeРодитель
nextElementSibling, previousElementSiblingli.nextElementSiblingСоседние элементы
nodeTypenode.nodeType === 11 — Element, 3 — Text

См. шпаргалку и примеры в Работа с HTML, события — События.

Свойства Element:

СвойствоЗначение
element.idзначение атрибута id
element.classNameстрока классов (class="...")
element.classListобъект для работы с классами (методы: add(), remove(), toggle())
element.innerHTMLHTML-содержимое внутри тега
element.outerHTMLэлемент целиком с открывающим и закрывающим тегом
element.textContentтекст (без HTML-тегов)
element.styleдоступ к CSS-стилям

Методы:

МетодПримерДействие
getAttribute()div.getAttribute('data-id')Получить атрибут
setAttribute()div.setAttribute('data-test', '123')Установить атрибут
removeAttribute()div.removeAttribute('hidden')Удалить атрибут
hasAttribute()div.hasAttribute('disabled')Проверить наличие атрибута
append() / prepend()div.append(newElement)Добавить элемент
remove()div.remove()Удалить элемент
closest()div.closest('.parent')Найти ближайший родительский элемент

Прочие объекты

Браузерные объекты

Браузерные объекты

Браузерные объекты – объекты, предоставляемые для работы с окружением:

ОбъектОписание
WindowГлобальный объект (вкладка браузера)
NavigatorИнформация о браузере
ScreenДанные об экране
HistoryУправление историей
LocationURL страницы

Свойства Window:

СвойстваОписаниеПример
window.innerWidthШирина области просмотра (px)window.innerWidth → 1200
window.innerHeightВысота области просмотра (px)window.innerHeight → 800
window.outerWidthШирина всего окна браузера (px)window.outerWidth → 1400
window.outerHeightВысота всего окна браузера (px)window.outerHeight → 900
window.locationОбъект Location (URL страницы)window.location.href
window.documentОбъект Document (DOM)window.document.title
window.localStorageЛокальное хранилище данныхwindow.localStorage.setItem('key', 'value')

Методы:

МетодОписаниеПример
window.alert()Показывает alert-окноwindow.alert("Привет!")
window.open()Открывает новое окно/вкладкуwindow.open("https://google.com")
window.scrollTo()Прокручивает страницуwindow.scrollTo(0, 100)
window.setTimeout()Выполняет код с задержкойsetTimeout(() => {}, 1000)
window.fetch()Отправляет HTTP-запросfetch("https://api.example.com")

★ Графика: Canvas

Объект CanvasRenderingContext2D позволяет рисовать на <canvas>. Полный разбор API — в Canvas 2D.

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 100); // Рисуем красный квадрат

Работа с файлами и системой

В браузере и Node.js есть объекты для работы с файлами, сетью и процессами.

В браузере:

File API: Чтение файлов через <input type= "file">:

const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
console.log(file.name); // Имя файла
});

Основные методы/свойства File API:

  • files – список выбранных файлов;
  • FileReader – чтение содержимого файла;
  • Blob – бинарные данные файла.

В Node.js:

  • File System (fs) — чтение/запись файлов – readFile, writeFile, promises;
  • HTTP/NET: создание серверов – createServer, request;
  • Buffer/Stream: работа с бинарными данными – Buffer.from(), stream.pipe();
  • Process — процессы – argv, cwd, exit.

И да, метода JSON.statham() нет. Вроде бы.


Структурированные данные

ArrayBuffer и SharedArrayBuffer

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

// Создание буфера размером 16 байт
const buffer = new ArrayBuffer(16);

console.log(buffer.byteLength); // 16
console.log(buffer); // ArrayBuffer { byteLength: 16 }

Для работы с данными внутри буфера используются типизированные массивы:

Код ITЗагрузка примера кода…

SharedArrayBuffer позволяет разделять буфер памяти между несколькими потоками выполнения (например, с помощью веб-воркеров):

// Создание разделяемого буфера
const sharedBuffer = new SharedArrayBuffer(1024);

// Создание представления
const sharedArray = new Int32Array(sharedBuffer);

// Запись данных
sharedArray[0] = 42;
sharedArray[1] = 100;

DataView

DataView предоставляет низкоуровневый интерфейс для чтения и записи данных произвольного типа в ArrayBuffer:

Код ITЗагрузка примера кода…

Указание порядка байтов (endianness):

const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);

// Запись с указанием порядка байтов
view.setInt32(0, 0x12345678, true); // little-endian
console.log(view.getInt32(0, true)); // 305419896

view.setInt32(0, 0x12345678, false); // big-endian
console.log(view.getInt32(0, false)); // 305419896

Atomics

Atomics предоставляет атомарные операции для работы с разделяемой памятью, обеспечивая потокобезопасность:

Код ITЗагрузка примера кода…

Синхронизация потоков с помощью wait и notify:

// В основном потоке
Atomics.store(sharedArray, 0, 0);

// В воркере
Atomics.wait(sharedArray, 0, 0); // Ожидает, пока значение не изменится
console.log("Продолжение выполнения");

// В основном потоке после изменения
Atomics.store(sharedArray, 0, 1);
Atomics.notify(sharedArray, 0); // Пробуждает ожидающий воркер

JSON

Объект JSON предоставляет методы для преобразования данных в формат JSON и обратно:

Код ITЗагрузка примера кода…

Форматирование при сериализации:

Код ITЗагрузка примера кода…

Использование функции-замены (replacer):

Код ITЗагрузка примера кода…


Управление памятью

WeakRef

WeakRef создаёт слабую ссылку на объект, позволяя сборщику мусора удалить объект, если на него нет других сильных ссылок:

Код ITЗагрузка примера кода…


FinalizationRegistry

FinalizationRegistry регистрирует колбэк, который вызывается после удаления объекта сборщиком мусора:

Код ITЗагрузка примера кода…

Практическое применение для управления ресурсами:

Код ITЗагрузка примера кода…


Абстракции управления

Iterator и AsyncIterator

Итераторы предоставляют стандартный способ перебора элементов коллекции:

Код ITЗагрузка примера кода…

Асинхронные итераторы для работы с асинхронными данными:

Код ITЗагрузка примера кода…


Promise

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

Код ITЗагрузка примера кода…

Статические методы Promise:

Код ITЗагрузка примера кода…


Generator и GeneratorFunction

Генераторы позволяют приостанавливать и возобновлять выполнение функции:

Код ITЗагрузка примера кода…

Генератор с параметрами:

function* counter() {
let count = 0;
while (true) {
const increment = yield count;
count += increment || 1;
}
}

const gen = counter();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next(5).value); // 6
console.log(gen.next(10).value); // 16

Делегирование генераторов:

function* gen1() {
yield 1;
yield 2;
}

function* gen2() {
yield 3;
yield* gen1(); // Делегирование
yield 4;
}

const gen = gen2();
console.log([...gen]); // [3, 1, 2, 4]

AsyncGenerator и AsyncGeneratorFunction

Асинхронные генераторы объединяют функциональность генераторов и промисов:

async function* asyncNumberGenerator() {
yield 1;
await new Promise(resolve => setTimeout(resolve, 1000));
yield 2;
await new Promise(resolve => setTimeout(resolve, 1000));
yield 3;
}

(async () => {
for await (let num of asyncNumberGenerator()) {
console.log(num); // 1, затем 2 (через 1с), затем 3 (через 2с)
}
})();

Практическое применение для потоковой загрузки данных:

async function* fetchPages(url, pages) {
for (let page = 1; page <= pages; page++) {
const response = await fetch(`${url}?page=${page}`);
const data = await response.json();
yield data;
}
}

(async () => {
for await (const pageData of fetchPages("/api/items", 3)) {
console.log("Загружена страница:", pageData);
}
})();

AsyncFunction

AsyncFunction — это конструктор для создания асинхронных функций динамически:

const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;

const asyncSum = new AsyncFunction('a', 'b', 'return a + b');

asyncSum(5, 3).then(result => console.log(result)); // 8

DisposableStack и AsyncDisposableStack

Эти объекты упрощают управление ресурсами, требующими очистки:

Код ITЗагрузка примера кода…

Асинхронная версия:

Код ITЗагрузка примера кода…


Рефлексия

Reflect

Reflect предоставляет методы для выполнения операций над объектами в функциональном стиле:

Код ITЗагрузка примера кода…


Proxy

Proxy позволяет перехватывать и переопределять операции над объектами:

Код ITЗагрузка примера кода…

Валидация данных через прокси:

Код ITЗагрузка примера кода…

Создание неизменяемого объекта:

Код ITЗагрузка примера кода…


Интернационализация

Intl

Объект Intl предоставляет интернационализированные функции форматирования:

// Текущая локаль
console.log(Intl.getCanonicalLocales("en-US")); // ["en-US"]
console.log(Intl.getCanonicalLocales("RU")); // ["ru"]

Intl.Collator

Collator обеспечивает сортировку строк с учётом локали:

Код ITЗагрузка примера кода…


Intl.DateTimeFormat

Форматирование дат и времени:

Код ITЗагрузка примера кода…

Форматирование для разных локалей:

const date = new Date(2024, 0, 15);

console.log(new Intl.DateTimeFormat("en-US").format(date)); // "1/15/2024"
console.log(new Intl.DateTimeFormat("de-DE").format(date)); // "15.1.2024"
console.log(new Intl.DateTimeFormat("ja-JP").format(date)); // "2024/1/15"
console.log(new Intl.DateTimeFormat("zh-CN").format(date)); // "2024/1/15"

Intl.NumberFormat

Форматирование чисел:

Код ITЗагрузка примера кода…


Intl.RelativeTimeFormat

Форматирование относительного времени:

Код ITЗагрузка примера кода…


Intl.ListFormat

Форматирование списков:

Код ITЗагрузка примера кода…


Intl.PluralRules

Определение формы множественного числа:

Код ITЗагрузка примера кода…


Intl.DisplayNames

Отображение названий локалей, регионов и языков:

Код ITЗагрузка примера кода…


Intl.Segmenter

Сегментация текста на графемы, слова или предложения:

Код ITЗагрузка примера кода…


Intl.Locale

Работа с локалями:

Код ITЗагрузка примера кода…


Практические примеры

Создание кэша с автоматической очисткой

Код ITЗагрузка примера кода…


Интернационализированный форматтер дат

Код ITЗагрузка примера кода…


Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


Навигация по теме объектов

Статья большая, поэтому удобнее изучать ее слоями:

  1. Сначала базовые объекты, свойства и методы.
  2. Потом прототипы и наследование.
  3. Затем дескрипторы, иммутабельность и метапрограммирование.

Практический чеклист по объектам в проекте:

  • отделяйте данные от поведения (DTO vs доменные объекты);
  • замораживайте конфиги (Object.freeze), если они не должны меняться;
  • избегайте глубоких мутаций без необходимости;
  • для сравнения структур пишите явную логику, а не ===.
const appConfig = Object.freeze({
apiBaseUrl: "/api",
retryCount: 3
});

Продолжение:

Содержание