Внутренние методы Object (спецификация ECMAScript)
Согласно спецификации, объект в JavaScript — не «коробка с ключами и значениями», а набор из 11 internal methods (+2 для callable). Привычное представление об объектах — это аналогия, не реальность.
«Согласно спецификации, объект — это некоторая коробка, в которой есть 13 методов и больше ничего нет. Нет в нём properties, ничего другого. Самое главное для определения семантики объекта — эти 13 методов» — автор, 6FqwosOqJCs.
11 базовых internal methods
В нотации спецификации записываются в двойных квадратных скобках [[Method]]:
| Метод | Что делает |
|---|---|
[[GetPrototypeOf]] |
возвращает прототип объекта |
[[SetPrototypeOf]] |
устанавливает прототип |
[[IsExtensible]] |
можно ли добавлять свойства |
[[PreventExtensions]] |
запрещает добавление свойств |
[[GetOwnProperty]] |
возвращает дескриптор собственного свойства |
[[DefineOwnProperty]] |
определяет собственное свойство |
[[HasProperty]] |
проверка наличия (включая прототип) |
[[Get]] |
чтение свойства |
[[Set]] |
запись свойства |
[[Delete]] |
удаление свойства |
[[OwnPropertyKeys]] |
список собственных ключей |
+2 для callable объектов
| Метод | Что делает |
|---|---|
[[Call]] |
вызывает функцию |
[[Construct]] |
вызывает как конструктор (new) |
Если у объекта есть [[Call]] — это callable (функция). Если ещё и [[Construct]] — может вызываться с new.
Ordinary vs Exotic Objects
Ordinary object — все 11 (или 13) методов следуют стандартным алгоритмам из спецификации. Это обычный {}.
Exotic object — хотя бы один метод переопределён собственным алгоритмом:
Proxy— все методы перехватываются handler-амиArray—[[DefineOwnProperty]]поддерживает поведениеlengthFunction— особое[[Call]]/[[Construct]]Arguments,String-обёртки,TypedArray,Module Namespace— у всех свои отклонения
Object literal — не объект, а команда
const o = { name: 'Marcus' };
«Object literal — это синтаксическая команда, которая заставляет внутреннюю машинерию определённым образом создать объект. Это не объект, а команда из нескольких подкоманд» — автор.
Литерал → команда OrdinaryObjectCreate(%Object.prototype%) + последовательность [[DefineOwnProperty]] для каждого поля.
Ключи: только строки и символы
«Числовых ключей в JavaScript не существует. Единственные ключи — строки и символы.»
const o = { 1: 'a' };
o[1] === o['1']; // true — '1' приведено к строке через ToPropertyKey
Алгоритм ToPropertyKey приводит любой не-Symbol к строке. Symbol — единственное исключение.
Property Descriptor
Каждое свойство в объекте описано property descriptor — внутренней структурой:
Object.getOwnPropertyDescriptor({ x: 1 }, 'x');
// { value: 1, writable: true, enumerable: true, configurable: true }
- Data descriptor:
value,writable - Accessor descriptor:
get,set - Общие:
enumerable,configurable
Reference Record и receiver
Когда мы пишем obj.method, под капотом создаётся Reference Record — структура с base (объект) и referenced name (имя). Это нужно, чтобы при вызове передать receiver (то, что станет this).
Поэтому obj.method и obj['method'] дают разный this, чем const m = obj.method; m — во втором случае reference уже разрешён, receiver потерян.
Прототип и [[Get]]
Алгоритм OrdinaryGet(obj, key, receiver):
- Получить дескриптор через
[[GetOwnProperty]]. - Если дескриптора нет — рекурсивно вызвать
[[Get]]у прототипа ([[GetPrototypeOf]]). - Если data — вернуть value. Если accessor — вызвать
getсreceiverкакthis.
Это и есть прототипная цепочка на уровне спецификации.
Зачем это знать
- Понимать Proxy — handler перехватывает именно эти 13 методов, один в один по имени.
- Понимать V8 — engine компилирует эти алгоритмы в машинный код с inline-кэшами.
- Не путаться в граничных случаях —
delete,in,Object.keys(),for-in,Reflect.ownKeysвсе читают разные методы.
Источники
- AsForJS · Что такое Object в JavaScript согласно официальной спецификации (2025-02-03, 168 мин) — главный источник
- AsForJS · JavaScript курс. Part 4: Поведение (2026-05-18)
- Timur · Proxy и Symbol в JavaScript (2018-11-26)
- ECMAScript spec §10.1 Ordinary Object Internal Methods