[object Object] иногда становится дорогим — и как одна строка делает исполнение кода медленнее.
const a = {
id: 1,
name: 'v',
age: 30
}const b = {}
b.id = 1
b.name = 'v'
b.age = 30delete obj.foo?
PiterJS · Алексей Козятинский
Podlodka React Crew · Анастасия Котова
Node Congress · Мерт Джан Алтын
function getId(obj) {
return obj.id // ← call site
}{ id, name, age }
{ id, name, age } = одна Map на всех
// literal — V8 видит сразу всю форму
const a = {
id: 1,
name: 'v',
age: 30
}
// stepwise — V8 строит форму по полю
const b = {}
b.id = 1
b.name = 'v'
b.age = 30%HaveSameMap(a, b) → false ·
v8-флаг --allow-natives-syntax// смешали — IC видит две формы
function getId(obj) {
return obj.id
}
getId(a) // Map#literal → mono ✓
getId(b) // Map#stepwise → poly ⚠
function makeUser(id, name, isAdmin) {
const user = {
id,
name
}
if (isAdmin) {
user.role = 'admin'
}
return user
}null.
delete — это катастрофаconst user = {
id: 1,
name: 'v',
tmp: 'love ts'
}
delete user.tmpundefined · объект выпал из transition tree
каждое чтение поля → hash lookup, IC бесполезен
user.tmp = null · поле остаётся в shape, IC живёт
delete
obj.id
delete → dictionarydelete уронил объект в dict mode в Node.js 22 и не вернулся в 24.
const u = { id: 1, tmp: 9 }
delete u.tmp % HasFastProperties(u)
// → truefast path сохраняется
const u = { id: 1, tmp: 9 }
delete u.tmp % HasFastProperties(u)
// → falsedictionary mode
const u = { id: 1, tmp: 9 }
delete u.tmp % HasFastProperties(u)
// → falsedictionary mode
--allow-natives-syntax).
false, когда объект ушёл в dict mode. С Node.js 22+ это происходит после одного delete.
delete уносит в dict mode · ×29Node.js: v22.18.0 | V8: 12.4.254.21-node.27 | Apple M4
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
• object shape: field read
--------------------------------------------- -------------------------------
literal (1 shape, fast path) 1.06 ns/iter 1.04 ns █
(986.57 ps … 19.65 ns) 1.34 ns █
stepwise (same order) 1.06 ns/iter 1.04 ns █▃
(986.57 ps … 13.38 ns) 1.37 ns ██
polymorphic IC (2 shapes) 1.19 ns/iter 1.16 ns █
(1.11 ns … 18.57 ns) 1.70 ns █
megamorphic IC (6 shapes) 3.30 ns/iter 3.19 ns █
(3.09 ns … 313.52 ns) 6.49 ns █
dictionary mode (after delete) 30.94 ns/iter 31.88 ns █
(20.14 ns … 358.08 ns) 91.30 ns ██▇
summary
literal (1 shape, fast path)
1x faster than stepwise (same order)
1.13x faster than polymorphic IC (2 shapes)
3.12x faster than megamorphic IC (6 shapes)
29.31x faster than dictionary mode (after delete)
Node.js: v24.14.1 | V8: 13.6.233.17-node.44 | Apple M4
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
• object shape: field read
--------------------------------------------- -------------------------------
literal (1 shape, fast path) 1.02 ns/iter 1.01 ns █
(946.04 ps … 19.96 ns) 1.43 ns ▄█
stepwise (same order) 1.07 ns/iter 1.03 ns █
(956.05 ps … 901.39 ns) 2.11 ns █
polymorphic IC (2 shapes) 1.12 ns/iter 1.11 ns █
(1.04 ns … 15.59 ns) 1.56 ns █
megamorphic IC (6 shapes) 3.17 ns/iter 3.11 ns █▅
(3.04 ns … 35.13 ns) 4.58 ns ██
dictionary mode (after delete) 14.08 ns/iter 16.30 ns █▃
(7.46 ns … 92.08 ns) 34.50 ns ▆██▄
summary
literal (1 shape, fast path)
1.05x faster than stepwise (same order)
1.1x faster than polymorphic IC (2 shapes)
3.12x faster than megamorphic IC (6 shapes)
13.82x faster than dictionary mode (after delete)
makeUser и parseUser — поля идут в одинаковм порядкеnull / undefined, но поле в shapedelete obj.propertyзамени на obj.property = null — shape стабильныйObject.create(null) в hot path≈ 9× оверхед против обычного литералаif (admin) user.role = ... — две формы из одной фабрикиdelete
Бенчи
obj-cost
канал
zero_deps