JavaScript Symbol

`Symbol` is a primitive type whose values are unique and are commonly used as collision-resistant object property keys. Symbols also provide standardized protocol hooks, such as `Symbol.iterator`, that let objects customize built-in language behavior.

A symbol is created with `Symbol()`, and each call produces a distinct primitive value. Even when two symbols have the same description, they are not equal. The optional description is mainly for debugging and does not determine identity.

Symbols can be used as object property keys alongside strings. A symbol-keyed property avoids accidental collisions with ordinary string property names, which is useful when adding metadata or defining library-level behavior on objects you do not fully control.

Symbol-keyed properties are intentionally excluded from several common string-key enumeration mechanisms. For example, `Object.keys()` and `for...in` do not include symbol keys. APIs such as `Object.getOwnPropertySymbols()` and `Reflect.ownKeys()` can retrieve them.

Some well-known symbols act as protocol hooks recognized by JavaScript itself. For example, an object can implement `[Symbol.iterator]()` to define how it is iterated by constructs such as `for...of`. These symbols therefore provide standardized extension points without requiring specially named string properties.

Key points

Interview questions

What are well-known symbols, and why are they important?

Well-known symbols are predefined symbol values that JavaScript uses as protocol hooks. Examples include `Symbol.iterator`, `Symbol.toPrimitive`, and `Symbol.toStringTag`. Objects can implement properties using these symbols to customize behavior expected by language features and standard APIs. This provides extensibility without relying on potentially conflicting string property names.

What is a JavaScript Symbol, and why would you use one?

A Symbol is a primitive value that is unique from every other ordinary symbol. It can be used as an object property key, which helps avoid accidental name collisions with string properties. This is useful for library metadata or properties that should not normally participate in string-key enumeration. Symbols are not equivalent to private fields, because symbol properties can still be discovered through reflection.

What happens when you use a Symbol as an object property key?

The symbol becomes a property key distinct from string keys. A property keyed by a symbol can be accessed only with that symbol value or through reflection that retrieves symbol keys. `Object.keys()` and `for...in` do not include it. APIs such as `Object.getOwnPropertySymbols()` and `Reflect.ownKeys()` can expose it.

What is the difference between `Symbol()` and `Symbol.for()`?

`Symbol()` creates a new symbol each time it is called, even if the descriptions match. `Symbol.for()` uses a global symbol registry and returns the same symbol for the same registry key. This makes `Symbol.for()` useful when independently loaded code needs to share a symbol by a known registry key. The registry key is a string, while the returned value is a symbol.

Are Symbol properties private, and how would you inspect them?

No. A symbol property is not private merely because its key is hard to guess. If code has the symbol, it can directly access the property, and reflection APIs can discover symbol keys. `Object.getOwnPropertySymbols()` returns an object's own symbol keys, while `Reflect.ownKeys()` returns both string and symbol own keys. JavaScript private class fields use `#name` when actual language-enforced privacy is required.