Symbol in JavaScript: a property key that never collides

A Symbol is a value unique by construction, used as a discreet property key and to plug an object into the language's own machinery.
3 min read
Believemy logo

Adding a property to an object you do not own is a risky move: if one library writes obj.id and another does the same, the second wipes out the first without a sound.

The symbol settles that at the root, by handing out a key nobody else can produce by accident.


Definition

A Symbol is a unique, immutable primitive value created by calling Symbol(). Two symbols are never equal, even when created with the same description.

JAVASCRIPT
const a = Symbol("id");
const b = Symbol("id");

console.log(a === b);        // false
console.log(a.description);  // "id"
console.log(typeof a);       // "symbol"

The description only serves debugging: it shows up in messages and in the console, without ever taking part in the comparison. That is what separates a symbol from a string, where two identical values are the same key.


A discreet property key

A symbol is used as a key inside brackets. The property exists and reads back normally, yet it escapes the ordinary walks.

JAVASCRIPT
const INTERNAL = Symbol("internal");
const account = { name: "Ada", [INTERNAL]: "token" };

console.log(Object.keys(account));      // [ 'name' ]
console.log(JSON.stringify(account));   // {"name":"Ada"}
console.log(account[INTERNAL]);         // "token"

Neither Object.keys, nor an in loop, nor JSON.stringify sees that key. The data travels with the object without polluting its public shape, which is exactly what libraries are after.


The well-known symbols

The language reserves a few symbols for plugging an object into its own machinery. The most useful is Symbol.iterator, which makes an object walkable by of and unfoldable by Spread (...).

JAVASCRIPT
const week = {
  days: ["monday", "tuesday", "wednesday"],
  [Symbol.iterator]() {
    let i = 0;
    const { days } = this;
    return {
      next: () =>
        i < days.length
          ? { value: days[i++], done: false }
          : { value: undefined, done: true },
    };
  },
};

for (const day of week) console.log(day);
console.log([...week]);   // [ 'monday', 'tuesday', 'wednesday' ]


Frequently asked questions

Question

Why does new Symbol() throw?

Because a symbol is a primitive, just like a number or a boolean, and not an object to be constructed. The new throws a TypeError saying Symbol is not a constructor. The function is called directly instead.

Question

Is a symbol-keyed property genuinely private?

No, it is discreet. Object.getOwnPropertySymbols lists every one of them, and whoever holds the symbol reads the value. For real confidentiality, the private fields of a class, prefixed with a hash, are what to use.

Question

What is Symbol.for for?

For sharing one symbol across separate pieces of code. Symbol.for("app.id") looks a global registry up and always hands back the same value, where Symbol("app.id") creates a new one on every call. Keep it for cases where sharing is intended.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.