V8 Hidden Classes (Shapes)
Hidden Class (он же Shape, Map) — внутренняя структура V8, описывающая «форму» объекта: список свойств и их порядок. Объекты с одинаковой shape делят один Hidden Class — это основа Inline Cache.
Что это / Зачем
JavaScript — динамический язык. Но V8 пытается ускорить доступ к свойствам, как если бы это были поля статически типизированной структуры. Для этого:
- При создании объекта присваивается Hidden Class
- Hidden Class знает offset каждого свойства внутри объекта
- Доступ
obj.x→ не "поиск в хэш-таблице", а "прочитай по offset X" - Объекты с одинаковыми свойствами в одинаковом порядке имеют одну shape
Пример transition'ов
const a = {}; // Hidden Class C0 (пустой)
a.x = 1; // C0 → C1 (есть x)
a.y = 2; // C1 → C2 (есть x, y)
const b = {}; // C0
b.x = 1; // C1 — та же что у a
b.y = 2; // C2 — та же что у a
// a и b разделяют C2 → одинаковая shape
const c = {};
c.y = 2; // C0 → C3 (есть y)
c.x = 1; // C3 → C4 (есть y, x)
// c имеет ДРУГОЙ Hidden Class — другой порядок!
Правила сохранения shape
- Добавляйте поля в одном порядке в конструкторе:
// Хорошо
class Point {
constructor(x, y) {
this.x = x; // всегда первое
this.y = y; // всегда второе
}
}
// Плохо — разные shapes
function Bad(x, y) {
if (random) { this.x = x; this.y = y; }
else { this.y = y; this.x = x; }
}
- Не используйте
delete— превращает объект в dictionary mode (медленная hashmap):
const obj = { x: 1, y: 2 };
delete obj.x; // ← shape сломан, объект в slow mode
- Не добавляйте поля после создания:
const obj = { x: 1 }; // shape: {x}
// ... 1000 строк кода ...
obj.y = 2; // shape transition в горячем месте — деопт
- Инициализируйте все поля сразу в
nullесли значения нет:
class User {
constructor {
this.name = null;
this.email = null;
this.age = null;
}
}
Связь с Inline Cache
Когда V8 видит function get(o) { return o.x }:
- Первый вызов: записывает в IC slot пару
(Hidden Class, offset для x) - Следующие вызовы с тем же Hidden Class: используют закешированный offset (monomorphic)
- Несколько Hidden Classes: polymorphic (медленнее)
- Много (>4): megamorphic — IC отключается, поиск через hashmap
Подводные камни
Object.create(null)создаёт объект без прототипа — отдельный shape- Spread
{...obj}создаёт новый объект с новым Hidden Class - Symbol-ключи учитываются в shape, но в отдельной структуре
Object.freezeсоздаёт frozen shape — read-only
🎓 Источники
- ⚡ [Производительность JS Обьекты в V8] · AsForJS · 2025-02-07 · YouTube
- Тезисы: V8 строит дерево hidden classes через transitions. Каждый объект — точка в этом дереве. Одинаковая shape = одна точка
- ⚡ [Производительность V8 объектов в примерах] · AsForJS · 2025-02-11 · YouTube
- Тезисы:
deleteломает shape — переход в dictionary mode.null-инициализация полей сохраняет shape
- Тезисы:
- 🎓 [Мономорфный и полиморфный код, инлайн-кэш, скрытые классы] · 2019-10-29 · YouTube
- Тезисы: монолитный код с одинаковыми shapes = быстрый. Полиморфизм/мегаморфизм = медленный. Это применимо ко ВСЕМ объектам, не только из class