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

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

Разработчику Архитектору
Сначала — общие понятия (раздел 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
});

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

Содержание