Symbols in JavaScript
Introduction
A Symbol is a unique primitive value—ideal for property keys that should not collide with string keys like "name" or "id". Well-known symbols (Symbol.iterator, Symbol.toStringTag, etc.) let libraries hook into language behavior without polluting public APIs.
Prerequisites
Create Symbols
javascript
// Each Symbol() is unique
const a = Symbol("label");
const b = Symbol("label");
console.log(a === b);
console.log(typeof a);Optional description helps debugging only—not equality.
Symbol Keys on Objects
javascript
// Hidden-ish metadata key
const id = Symbol("id");
const user = {
name: "Ada",
[id]: 9001,
};
console.log(user.name);
console.log(user[id]);Symbol keys are skipped by Object.keys and for...in unless you use Object.getOwnPropertySymbols.
Global Symbol Registry
javascript
// Same symbol across files/realms
const shared = Symbol.for("app.config");
const again = Symbol.for("app.config");
console.log(shared === again);
console.log(Symbol.keyFor(shared));Well-Known Symbols
javascript
// Customize iteration
const collection = {
items: [1, 2, 3],
[Symbol.iterator]() {
let i = 0;
const data = this.items;
return {
next() {
if (i < data.length) return { value: data[i++], done: false };
return { done: true };
},
};
},
};
for (const x of collection) {
console.log(x);
}Other examples: Symbol.toStringTag, Symbol.hasInstance.
Symbol.iterator on Built-ins
Arrays, strings, Map, and Set already implement it—custom objects opt in as above.
Mini Example: Plugin Hook Key
javascript
const HOOK = Symbol("plugin.hook");
const plugins = [
{
name: "logger",
[HOOK](ctx) {
console.log("before", ctx.step);
},
},
];
function run(step) {
const ctx = { step };
for (const plugin of plugins) {
const fn = plugin[HOOK];
if (fn) fn(ctx);
}
}
run("save");FAQ
Symbol vs string key?
Symbols avoid name clashes; strings are normal public fields.
JSON and Symbols?
JSON.stringify ignores symbol-keyed properties.
Can I coerce Symbol to string?
String(sym) works; implicit + concatenation throws.