Under the Hood of V8: How JavaScript Properties Actually Work
If you’ve ever wondered why some JavaScript code runs faster than others, the answer often lies in how V8—Chrome’s JavaScript engine—handles properties. It’s a fascinating tale of trade-offs between flexibility and performance.
The Core Insight
From a JavaScript developer’s perspective, objects are simple: they’re dictionaries with string keys and arbitrary values. Under the hood, V8 maintains at least 20 different internal representations for properties, each optimized for specific access patterns.
This isn’t over-engineering—it’s survival. JavaScript powers half the internet, and every millisecond of performance matters at scale.
The HiddenClass System
Every JavaScript object in V8 has an associated HiddenClass (conceptually similar to classes in traditional OOP languages). Objects with the same structure—same properties in the same order—share the same HiddenClass.
Here’s the key insight: when you add a new property to an object, V8 creates a new HiddenClass. This transition tree allows V8 to optimize by “knowing” the shape of objects. If the optimizing compiler sees code accessing properties on objects with a known HiddenClass, it can inline those accesses directly—no runtime lookup needed.
This is why property order matters in JavaScript:
// These might share a HiddenClass after optimization
const a = { x: 1, y: 2 };
const b = { x: 3, y: 4 };
// This creates a different HiddenClass
const c = { y: 1, x: 2 };
Three Types of Named Properties
V8 distinguishes between three storage strategies:
In-object properties: Stored directly on the object itself. Fastest access but limited by initial object size.
Fast properties: Stored in a separate “properties store” with access via index. Meta information lives in the descriptor array on the HiddenClass.
Slow/dictionary properties: Used when objects have many additions/deletions. Properties live in a self-contained dictionary, losing the benefits of HiddenClass sharing but allowing flexible modification.
Elements: The Array Complexity
Integer-indexed properties (elements) are even more complex. V8 maintains approximately 20 different “element kinds”:
- Packed vs. Holey: Does the array have gaps?
- Fast vs. Dictionary: Is it a simple array or a sparse dictionary?
- Smi vs. Double: Are elements small integers or floating-point numbers?
V8 optimizes each case differently, even switching representations dynamically as arrays grow or shrink.
Why This Matters for Developers
Understanding these internals helps you write faster JavaScript:
- Define properties in consistent order to help V8’s HiddenClass system
- Prefer arrays with consistent element types (Smi elements are fastest)
- Avoid deleting array elements if performance matters
- Use
Array.prototypemethods that work well with packed elements
Looking Ahead
V8’s property system represents a fascinating balance: maintaining JavaScript’s dynamic flexibility while extracting every possible performance optimization. As JavaScript continues evolving—with new features like records and tuples—the engine will need new strategies.
The takeaway? Your “simple” const obj = {} is anything but simple underneath.
Based on analysis of “Fast Properties” from V8 Dev Blog