Exploring JS Symbols

Priyanshu Chauhan
3 min readMay 9, 2024

--

Hey there, fellow developers! Today, I’m diving into an often overlooked but incredibly useful feature in JavaScript: Symbols. These little nuggets are unique, and immutable, and give us a powerful way to add metadata-like properties to objects without worrying about name clashes. So, let’s explore how to use Symbols effectively in our projects.

What Exactly Are Symbols?

A Symbol is a primitive data type introduced in ES6 (ECMAScript 2015) that is unique and immutable. You can think of them as tokens that serve as unique IDs.

Here’s how you create Symbols:

const sym1 = Symbol();
const sym2 = Symbol("foo");
const sym3 = Symbol("foo");

console.log(sym1); // Symbol()
console.log(sym2); // Symbol(foo)
console.log(sym3); // Symbol(foo)
console.log(sym2 === sym3); // false

Every Symbol is unique, even if they have the same description. Hence, sym2 is not equal to sym3.

Avoiding new with Symbols

Interestingly, Symbols break the common pattern in JavaScript since you can’t use the new keyword with them:

// This will throw a TypeError
const sym = new Symbol(); // TypeError: Symbol is not a constructor

To create a Symbol wrapper object, which is rarely needed, use the Object() function:

const symObj = Object(sym2);
console.log(typeof symObj); // "object"

Symbols and Their Uses

Symbols are ideal for adding properties to objects when you want to avoid accidental name collisions. This feature is especially useful in large projects or libraries where you don’t control all the code.

Here’s how you can use Symbols as property keys:

const uniqueKey = Symbol('userId');
const user = {
[uniqueKey]: '12345'
};

console.log(user[uniqueKey]); // '12345'

System Symbols: Well-Known Symbols

JavaScript has predefined system Symbols with special behaviors, referred to as well-known Symbols. For instance, Symbol.iterator defines the iteration behavior of an object:

const collection = {
items: [1, 2, 3],
[Symbol.iterator]: function* () {
for (let item of this.items) {
yield item;
}
}
};

for (let item of collection) {
console.log(item); // Outputs 1, 2, 3
}

Managing Symbols Globally

For Symbols that you wish to reuse across different parts of your code or even different iframes or service workers, you can use the global Symbol registry:

// Creating and retrieving Symbols from the global registry
const globalSym = Symbol.for("app.unique");
console.log(Symbol.keyFor(globalSym)); // "app.unique"

Interaction with Other Object Features

Symbols are not enumerable in for...in loops, and they won’t be returned by Object.getOwnPropertyNames(). However, you can retrieve them using Object.getOwnPropertySymbols():

const obj = {
[Symbol('mySymbol')]: 42
};

const symbolKeys = Object.getOwnPropertySymbols(obj);
console.log(obj[symbolKeys[0]]); // 42

Conclusion

Symbols provide a robust way to handle properties that should not interfere with other object attributes, maintaining a clean and organized codebase. Whether it’s for managing internal states, creating private-like properties, or ensuring that extensions to objects don’t clash with existing methods, Symbols can be your go-to tool.

I hope this exploration helps you understand and utilize JavaScript Symbols in your projects. Happy coding!

--

--

Priyanshu Chauhan
Priyanshu Chauhan

Written by Priyanshu Chauhan

Senior Frontend Engineer at Razorpay | JS 🤌🏻

No responses yet