DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. JavaScript Symbol: The Forgotten Primitive
XLinkedInReddit
MediumFrontend Engineering

JavaScript Symbol: The Forgotten Primitive

D
DevPrep Team
February 10, 2026·2 min read·0
Table of Contents
  • Creating Symbols
  • Use Case 1: Collision-Free Property Keys
  • Use Case 2: Well-Known Symbols
  • Symbol.toPrimitive
  • Symbol Properties Are Hidden
  • When to Use Symbols

Symbols are unique, immutable identifiers. They solve real problems like property collision and protocol implementation.

Creating Symbols

const sym1 = Symbol("description");
const sym2 = Symbol("description");
sym1 === sym2; // false! Every Symbol is unique

// Global symbols (shared across realms)
const globalSym = Symbol.for("app.config");
Symbol.for("app.config") === globalSym; // true

Use Case 1: Collision-Free Property Keys

// Library code — guaranteed no collision with user properties
const INTERNAL_STATE = Symbol("internalState");
const VALIDATOR = Symbol("validator");

class Form {
  [INTERNAL_STATE] = { dirty: false, submitted: false };
  [VALIDATOR] = null;

  setValidator(fn) { this[VALIDATOR] = fn; }
  
  submit() {
    this[INTERNAL_STATE].submitted = true;
    if (this[VALIDATOR]) this[VALIDATOR](this.data);
  }
}

// User can't accidentally overwrite internal state
const form = new Form();
form.internalState; // undefined (not the same property!)

Use Case 2: Well-Known Symbols

// Symbol.iterator — make objects iterable
class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }

  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;
    return {
      next() {
        return current <= end
          ? { value: current++, done: false }
          : { done: true };
      }
    };
  }
}

for (const n of new Range(1, 5)) console.log(n); // 1, 2, 3, 4, 5
[...new Range(1, 3)]; // [1, 2, 3]

Symbol.toPrimitive

class Money {
  constructor(amount, currency) {
    this.amount = amount;
    this.currency = currency;
  }

  [Symbol.toPrimitive](hint) {
    if (hint === "number") return this.amount;
    if (hint === "string") return `${this.amount} ${this.currency}`;
    return this.amount;
  }
}

const price = new Money(42, "USD");
+price;       // 42
`${price}`;   // "42 USD"

Symbol Properties Are Hidden

const obj = { [Symbol("secret")]: "hidden", visible: "shown" };

Object.keys(obj);             // ["visible"]
JSON.stringify(obj);          // {"visible":"shown"}
Object.getOwnPropertySymbols(obj); // [Symbol(secret)]

When to Use Symbols

  • Library/framework internal properties
  • Implementing protocols (iterator, toPrimitive)
  • Enum-like constants that are guaranteed unique
  • Metadata that shouldn't appear in serialization

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • Creating Symbols
  • Use Case 1: Collision-Free Property Keys
  • Use Case 2: Well-Known Symbols
  • Symbol.toPrimitive
  • Symbol Properties Are Hidden
  • When to Use Symbols

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.