Symbols & Well-Known Symbols

A Symbol is a unique, primitive value created with Symbol() that serves as a collision-proof object key and lets you hook into built-in language behaviors through well-known symbols like Symbol.iterator .

Learn Symbols & Well-Known Symbols in our free JavaScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Symbols are how you add hidden, non-colliding metadata to objects and how you teach your own objects to work with for...of , spread, and type coercion.

📚 Prerequisites: You should know objects, object iteration , and the idea of primitive types. Symbols are a primitive type just like numbers and strings.

🔣 Real-World Analogy: A Symbol is like a numbered cloakroom ticket :

Symbol("desc") returns a value guaranteed to differ from every other symbol. The string you pass is only a description for debugging — two symbols with the same description are still not equal. Used as object keys, symbols never clash with string keys, and they're invisible to for...in , Object.keys , and JSON.stringify , which makes them ideal for private-ish metadata.

Not truly private: symbol keys are hidden from normal iteration but Object.getOwnPropertySymbols can still find them. Use them for de-facto privacy, not security.

Plain Symbol() is private and unshareable. When you need the same symbol in different places, use Symbol.for("key") : it looks up a global registry, creating the symbol once and returning that identical symbol on every later call — even from another module. Symbol.keyFor recovers the registry key from such a symbol.

Namespace your keys (e.g. "myapp.userId" ) so registry symbols from different libraries don't accidentally collide on a common word.

JavaScript reserves a set of well-known symbols to customize language behavior. Define a [Symbol.iterator] method and your object suddenly works with for...of and the spread operator. Define [Symbol.toPrimitive] and you control how your object converts to a number or string in arithmetic and template literals.

Iterables power the language: arrays, strings, Maps, and Sets are all iterable because they implement Symbol.iterator . Now your objects can join the club.

Add a symbol key to the object so it stays out of Object.keys .

Predict the output before revealing the answer.

false — every Symbol() call makes a new, unique value.

true — Symbol.for returns the same registry symbol for a given key.

{' '} — symbol keys are skipped by JSON.stringify .

Make a team object iterable so spreading it yields its member names.

Up next: Getters, Setters & Property Descriptors — computed and protected properties. ⚙️

Practice quiz

What is logged? console.log(Symbol('id') === Symbol('id'));

  • true
  • undefined
  • false
  • It throws

Answer: false. Every Symbol() call makes a brand-new unique value; the description does not affect identity.

What is the role of the string passed to Symbol('id')?

  • It is just a description for debugging
  • It makes equal symbols
  • It registers the symbol globally
  • It sets the symbol's value

Answer: It is just a description for debugging. The description is only a debugging label; two symbols with the same description are still unequal.

What does Symbol.for('app.id') === Symbol.for('app.id') evaluate to?

  • false
  • undefined
  • It throws
  • true

Answer: true. Symbol.for looks up a shared global registry, returning the same symbol for a given key every time.

How are symbol keys treated by Object.keys and JSON.stringify?

  • They are included
  • They are skipped/hidden
  • They cause an error
  • They are converted to strings

Answer: They are skipped/hidden. Symbol keys are invisible to for...in, Object.keys, and JSON.stringify — handy for de-facto private metadata.

Which method reveals symbol keys that Object.keys omits?

  • Object.getOwnPropertySymbols
  • Object.entries
  • Object.getOwnPropertyNames
  • Reflect.keys

Answer: Object.getOwnPropertySymbols. Object.getOwnPropertySymbols lists an object's symbol keys.

Defining a [Symbol.iterator] method on an object lets it work with:

  • JSON.stringify
  • Math operations
  • for...of and the spread operator
  • Object.freeze

Answer: for...of and the spread operator. Symbol.iterator is a well-known symbol that enables for...of and spread on your object.

What does Symbol.toPrimitive let you control?

  • JSON serialization
  • How the object converts to a number or string
  • Garbage collection
  • Property enumeration order

Answer: How the object converts to a number or string. Symbol.toPrimitive customizes coercion in arithmetic and template literals.

What is logged? console.log('id: ' + Symbol('x'));

  • 'id: Symbol(x)'
  • 'id: undefined'
  • An empty string
  • A TypeError

Answer: A TypeError. Implicitly coercing a symbol to a string with + throws; use .toString() or String() explicitly.

How do you use a symbol stored in a variable sym as an object key?

  • { sym: 1 }

Use a computed key { [sym]: 1 }; { sym: 1 } would just use the string 'sym'.

What does Symbol.keyFor return for a symbol created with plain Symbol('z')?

  • 'z'
  • An empty string
  • undefined
  • It throws

Answer: undefined. Symbol.keyFor only finds registry symbols (from Symbol.for); a private Symbol() returns undefined.