Symbols are unique, immutable primitive values used for property keys and metaprogramming. Here's how to use them effectively.
Basic Usage#
Hidden Properties#
Symbol.for() - Global Registry#
Well-Known Symbols#
Symbol.toStringTag#
Symbol.toPrimitive#
Symbol.hasInstance#
Symbol.species#
Symbol.isConcatSpreadable#
Symbol.match/replace/search/split#
Private-like Properties#
Plugin/Extension Keys#
Type Checking with Symbols#
Best Practices#
Usage:
✓ Unique property keys
✓ Hidden metadata
✓ Well-known symbol customization
✓ Avoiding name collisions
Global Registry:
✓ Use Symbol.for() for shared symbols
✓ Use descriptive key names
✓ Namespace keys (e.g., 'myapp.feature')
✓ Check Symbol.keyFor() when needed
Well-Known Symbols:
✓ Symbol.iterator for iterables
✓ Symbol.toStringTag for debugging
✓ Symbol.toPrimitive for coercion
✓ Symbol.hasInstance for instanceof
Avoid:
✗ Symbols for true privacy (use #private)
✗ Overusing symbols
✗ Forgetting symbols are not enumerable
✗ Converting symbols to strings accidentally
Conclusion#
Symbols provide unique identifiers for object properties and enable metaprogramming through well-known symbols. Use them for hidden properties, avoiding naming collisions in libraries, and customizing object behavior like iteration and type coercion. The global registry (Symbol.for) enables cross-realm symbol sharing. While not truly private, symbols are hidden from most iteration methods, making them useful for metadata and internal properties.