Symbol

Added in ves6 · Updated March 14, 2026 · Built-in Objects
javascript symbol es6

Symbol is a built-in object that creates a unique identifier. Symbols are often used as object property keys to avoid naming collisions, and they serve as the foundation for well-known symbols that customize JavaScript behavior.

Creating Symbols

Create a Symbol using the Symbol() function:

const sym = Symbol();
typeof sym   // "symbol"

// With a description (useful for debugging)
const namedSym = Symbol("mySymbol");
const anotherSym = Symbol("mySymbol");

namedSym === anotherSym   // false - each Symbol is unique

The description is purely for debugging purposes and does not affect identity:

Symbol("test") === Symbol("test")   // false

Using Symbols as Property Keys

Symbols are useful as object property keys because they’re guaranteed to be unique:

const uniqueKey = Symbol("unique");

const obj = {
  [uniqueKey]: "secret value",
  regularKey: "public value"
};

obj[uniqueKey]    // "secret value"
obj.regularKey    // "public value"

This makes Symbols ideal for:

  • Defining private-like properties
  • Adding properties to objects without risking name conflicts
  • Creating constants that won’t clash with other code

Well-Known Symbols

JavaScript provides several built-in “well-known” Symbols that customize object behavior:

Symbol.iterator

Defines the default iterator for an object:

const iterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};

[...iterable]   // [1, 2, 3]

Symbol.toStringTag

Customizes the default string description:

const obj = {
  [Symbol.toStringTag]: "MyCustomObject"
};

Object.prototype.toString.call(obj)   // "[object MyCustomObject]"

Symbol.hasInstance

Allows customizing instanceof behavior:

class CustomArray {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

[] instanceof CustomArray   // true

Symbol.toPrimitive

Customizes object-to-primitive conversion:

const obj = {
  value: 10,
  [Symbol.toPrimitive](hint) {
    return this.value;
  }
};

+obj    // 10
obj + 5 // 15

Getting Symbol Values

Access existing symbols using Object.getOwnPropertySymbols():

const sym = Symbol("test");
const obj = { [sym]: "value" };

Object.getOwnPropertySymbols(obj)   // [Symbol(test)]

Use Symbol.for() to create or retrieve shared symbols:

const globalSym = Symbol.for("shared");
const sameSym = Symbol.for("shared");

globalSym === sameSym   // true - same symbol from global registry

Symbol.keyFor(globalSym)   // "shared"

Practical Examples

Creating Enum-like Values

const Direction = {
  UP: Symbol("UP"),
  DOWN: Symbol("DOWN"),
  LEFT: Symbol("LEFT"),
  RIGHT: Symbol("RIGHT")
};

function move(direction) {
  switch (direction) {
    case Direction.UP:    return "moving up";
    case Direction.DOWN:  return "moving down";
    // ...
  }
}

move(Direction.UP)   // "moving up"

Defining Private Properties

const _counter = Symbol("counter");

class Counter {
  constructor() {
    this[_counter] = 0;
  }
  
  increment() {
    this[_counter]++;
    return this[_counter];
  }
}

const c = new Counter();
c.increment();   // 1
c._counter;      // undefined - not directly accessible

Limitations

  • Symbols as property keys are not enumerable in for...in loops
  • Object.keys() and Object.getOwnPropertyNames() don’t return Symbol keys
  • Symbols are not serialized in JSON.stringify()
  • Each Symbol() call creates a new unique value

See Also