Symbol

Symbol is a primitive data type introduced in ES6. Each Symbol value is unique and immutable. That is what makes Symbols useful as property keys: a Symbol key will not conflict with any other key.

Creating Symbols

const sym1 = Symbol();
const sym2 = Symbol();

console.log(sym1 === sym2);  // false - each Symbol is unique

// Symbols can have descriptions (for debugging)
const sym3 = Symbol("mySymbol");
console.log(sym3.toString());  // "Symbol(mySymbol)"

The description is just a label. It does not affect uniqueness:

const a = Symbol("id");
const b = Symbol("id");
console.log(a === b);  // false - still unique

Symbols as Property Keys

We can use a Symbol as an object property key. Such a property will not conflict with a string key:

const id = Symbol("id");

const user = {
  name: "Alice",
  [id]: 12345,  // Symbol as key (computed property syntax)
};

console.log(user.name);  // "Alice"
console.log(user[id]);  // 12345

Symbol Properties are Hidden

Symbol-keyed properties do not appear in normal enumeration:

const secret = Symbol("secret");

const obj = {
  visible: "I am visible",
  [secret]: "I am hidden",
};

console.log(Object.keys(obj));  // ["visible"]
console.log(JSON.stringify(obj));  // {"visible":"I am visible"}

for (const key in obj) {
  console.log(key);  // Only logs "visible"
}

// But they can be accessed directly
console.log(obj[secret]);  // "I am hidden"

// And retrieved with specific methods
console.log(Object.getOwnPropertySymbols(obj));  // [Symbol(secret)]

This makes Symbols useful for adding metadata or internal properties that should not interfere with normal object usage.

Global Symbol Registry

Sometimes we need to share a Symbol across different parts of the code. The global Symbol registry is there for that:

// Create or retrieve a Symbol from the global registry
const globalSym = Symbol.for("app.id");

// Same key returns the same Symbol
const sameSym = Symbol.for("app.id");
console.log(globalSym === sameSym);  // true

// Get the key for a registered Symbol
console.log(Symbol.keyFor(globalSym));  // "app.id"

// Regular Symbols are not in the registry
const localSym = Symbol("local");
console.log(Symbol.keyFor(localSym));  // undefined