Now Reading:

Mastering Symbols and Symbol Properties In Javascript

Introduction

#

If you've ever worked with JavaScript, you've probably encountered data types like strings, numbers, objects, and arrays. But did you know there’s another, more mysterious primitive type called Symbols? They’re not as widely discussed as other data types, but mastering Symbols can give you new powers in JavaScript—especially when working on large codebases or creating libraries where you need to avoid name collisions.

In this article, we’ll dive deep into Symbols, understand their use cases, and explore how they differ from other data types. We’ll also touch on symbol properties, their unique behavior, and how they help with creating more flexible, robust JavaScript applications.

What Are Symbols?

#

A Symbol is a primitive data type introduced in ES6 (ECMAScript 2015). It is a unique, immutable value that is primarily used to create unique object keys. What makes Symbols stand out is that, even if two symbols have the same description, they are always unique.

Here's a simple example:


_10
const symbol1 = Symbol('description');
_10
const symbol2 = Symbol('description');
_10
_10
console.log(symbol1 === symbol2); // false

Despite both symbol1 and symbol2 having the same description ('description'), they are completely different values. This uniqueness makes Symbols incredibly useful for defining keys in objects, especially when you want to avoid accidental key collisions.

Why Use Symbols?

Symbols offer two primary benefits:

  1. Uniqueness: As we’ve seen, no two symbols are the same, even if they share a description. This ensures that when you define properties on objects using Symbols, they won’t conflict with other properties.
  2. Non-enumerable: By default, Symbol properties are not included in normal object property enumerations (such as for...in loops or Object.keys()), providing a layer of protection for these properties.

Using Symbols as Object Keys

#

Let’s start by seeing how Symbols can be used as object keys. In JavaScript, most object keys are strings, but Symbols allow you to create object properties that are unique and hidden from loops like for...in.


_10
const animal = {
_10
name: 'Dog'
_10
};
_10
_10
const species = Symbol('species');
_10
animal[species] = 'Canine';
_10
_10
console.log(animal.name); // 'Dog'
_10
console.log(animal[species]); // 'Canine'

In this example, the species Symbol is used as a key in the animal object. If you inspect the object, you'll see only the name property:


_10
console.log(Object.keys(animal)); // ['name']

Notice that species does not show up because Symbols are non-enumerable by default. This means for...in, Object.keys(), and similar methods will not pick up Symbol properties unless explicitly asked for with methods like Object.getOwnPropertySymbols():


_10
console.log(Object.getOwnPropertySymbols(animal)); // [ Symbol(species) ]

Global Symbols: Symbol.for() and Symbol.keyFor()

#

Symbols created with the Symbol() function are unique and cannot be referenced elsewhere in your code. However, there are times when you need to use the same Symbol across different parts of your codebase. That’s where global Symbols come into play.

JavaScript provides the Symbol.for() method to create and access global symbols. If a Symbol with a given key already exists, Symbol.for() returns that existing Symbol. Otherwise, it creates a new one.


_10
const globalSymbol1 = Symbol.for('global');
_10
const globalSymbol2 = Symbol.for('global');
_10
_10
console.log(globalSymbol1 === globalSymbol2); // true

Here, globalSymbol1 and globalSymbol2 are the same Symbol because they both refer to the same global key ('global'). To retrieve the key of a global Symbol, you can use Symbol.keyFor():


_10
console.log(Symbol.keyFor(globalSymbol1)); // 'global'

Built-In Well-Known Symbols

#

JavaScript includes several well-known Symbols that are used to customize how certain behaviors of objects work. These well-known Symbols are predefined by the language and can be used to modify object behaviors like iteration, string conversion, and more.

Some of the most common well-known Symbols include:

  • Symbol.iterator: Used to define the default iterator for an object, allowing you to customize how an object behaves in for...of loops.
  • Symbol.toStringTag: Controls the default string description of an object (as returned by Object.prototype.toString()).

Let’s look at an example of using Symbol.iterator:


_12
const dog = {
_12
name: 'Rex',
_12
age: 5,
_12
[Symbol.iterator]: function* () {
_12
yield this.name;
_12
yield this.age;
_12
}
_12
};
_12
_12
for (const prop of dog) {
_12
console.log(prop); // 'Rex', 5
_12
}

In this case, by adding a custom iterator using Symbol.iterator, we can control how our dog object behaves in for...of loops. Without this symbol, dog would not be iterable.

Symbols in Real Projects

#

Now, let’s consider a practical use case for Symbols: a plugin system for a JavaScript library. Let’s say we are building a library where developers can attach plugins. We don’t want the plugin properties to interfere with core functionality, so we use Symbols to keep plugin-specific keys hidden and unique.


_18
const PLUGIN_KEY = Symbol('plugin');
_18
_18
function attachPlugin(libObject, plugin) {
_18
libObject[PLUGIN_KEY] = plugin;
_18
}
_18
_18
function getPlugin(libObject) {
_18
return libObject[PLUGIN_KEY];
_18
}
_18
_18
// Example usage:
_18
const myLibrary = { name: 'AwesomeLib' };
_18
_18
const myPlugin = { name: 'SuperPlugin' };
_18
attachPlugin(myLibrary, myPlugin);
_18
_18
console.log(myLibrary.name); // 'AwesomeLib'
_18
console.log(getPlugin(myLibrary)); // { name: 'SuperPlugin' }

In this example, we use a Symbol to store the plugin in myLibrary, ensuring that it won’t accidentally conflict with any other properties in the library.

Conclusion

#

In this article, we’ve explored the mysterious and powerful Symbols in JavaScript. We’ve seen how they can help create unique, hidden object keys and avoid property collisions—perfect for scenarios where you need to manage complex systems or libraries. Additionally, we touched on global Symbols and well-known Symbols, showing their importance in customising object behaviours.

  • Symbols are unique and immutable, perfect for creating object keys that won’t clash.
  • They are non-enumerable, keeping them hidden from common operations like for...in.
  • You can use global Symbols when you need to reference the same Symbol across different parts of your code.
  • Well-known Symbols allow you to customize object behaviors like iteration and string conversion.

With these tools at your disposal, you can create more robust, flexible JavaScript applications. Keep exploring Symbols, and you’ll find new ways to make your code more maintainable and less prone to conflicts.

Further Reading

Reinforce Your Learning

One of the best ways to reinforce what your learning is to test yourself to solidify the knowlege in your memory.
Complete this 2 question quiz to see how much you remember.

1) What is the primary benefit of using Symbols as object keys in JavaScript?
file under:
Javascript

Thanks alot for your feedback!

The insights you share really help me with improving the quality of the content here.

If there's anything you would like to add, please send a message to:

[email protected]

Was this article this helpful?

D is for danny

About the author

Danny Engineering

A software engineer with a strong belief in human-centric design and driven by a deep empathy for users. Combining the latest technology with human values to build a better, more connected world.

Gobacktothetop

Made with 🥰 in 🏴󠁧󠁢󠁥󠁮󠁧󠁿

©2025 All rights reserved.