Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / ES6

Basics of JavaScript Symbols

4.94/5 (8 votes)
31 Jul 2020CPOL5 min read 6.3K  
An introduction to JavaScript Symbol type
In this article, we are going to explore the JavaScript Symbol type. Moreover, we are going to answer the following questions: what is it? how to create one? what are the wrong ways to create a JavaScript Symbol? and a whole lot more.

Introduction

Symbols are the newest JavaScript primitive as of this writing. In fact, many developers aren’t aware that this feature exists, including me at first. Bringing in a new feature to a language means benefits to the language and we should understand the particular use of a certain feature. Therefore, we are going to tackle the benefits and its particular usage of JavaScript symbols. OK, then let’s get started.

Table of Contents

What is JavaScript Symbol?

JavaScript Symbol is a new primitive type introduced in ES6. In addition, a symbol is a unique and immutable value. Creating a new symbol is quite easy, you just need to call the Symbol() function which returns a unique symbol every time it is invoked. Will get into examples in later sections.

Benefits and Usage of JavaScript Symbol?

Creating a new JavaScript Symbol is always unique

As we have described in the previous section, we said that in order to create a new JavaScript symbol, we just need to call the Symbol function. Another thing to mention about it, symbols don’t have literal form; thus, we can only use the Symbol() function to create one.

See the example below.

JavaScript
//how to create a Symbol 

const mySymbol1 = Symbol();
const mySymbol2 = Symbol();

console.log(mySymbol1, mySymbol2);
//output: Symbol() Symbol()

JavaScript Symbol with description, mainly used for debugging

Now, that we have seen how to create a new JavaScript Symbol. Let’s not forget that, a Symbol() function takes an optional string parameter which represents that description of the Symbol. Based on my experience, the description is used for debugging purposes but not to access the Symbol itself.

See the example below:

JavaScript
//* how to create a Symbol with description

const mySymbolWithDescription1 = Symbol("First description");
const mySymbolWithDescription2 = Symbol("Second description");

console.log(mySymbolWithDescription1, mySymbolWithDescription2);
//output: Symbol(First description) Symbol(Second description)

JavaScript Symbol with the same description isn't equal

Symbols are always 100% guaranteed to be unique. Remember, that description is just a label that doesn't affect anything. Again, the description is just a label nothing more nothing less.

See the example below:

JavaScript
//Symbol with same description aren't equal 

const mySymbol_1 = Symbol("Cat");
const mySymbol_2 = Symbol("Cat");

console.dir(mySymbol_1 === mySymbol_2);
//output: false

Symbol() function when invoking a new instance

The first time I learned JavaScript Symbol, I thought I can create a new instance by using the Symbol() function. Eventually, it throws an error that says: “Symbol is not a constructor” when creating a new instance.

See the example below:

JavaScript
//how not to create a Symbol

try {
    const _newSymbols = new Symbol();
} catch (error) {
    console.dir(error.message);   //output: Symbol is not a constructor
}

So, as you can see in the example above, using a new keyword to create a new instance of the Symbol isn't going to work because based on our previous section, we have to directly invoke the Symbol() function.

JavaScript Symbol type and conversion to a string

It's always been fun to use the typeof operator. Thus, the result would be a symbol and not an object because it is primitive.

Based on my observation, JavaScript types support implicit conversion to string. However, Symbol type doesn't auto-convert. You really need to explicitly call the .toString() method.

Check type using the typeof operator

JavaScript
//Let's check if the type name of Symbol 
const mySymbolType = Symbol();

console.log(typeof mySymbolType);
//output: symbol   

Call the type Symbol inside the alert function

JavaScript
const mySymbolType = Symbol();

alert(mySymbolType);
//output: Uncaught TypeError: Cannot convert a Symbol value to a string

Explicit usage of .toString() and use of description property

JavaScript
const _newSymbols2 = Symbol("Hello");
console.log(_newSymbols2.toString());  //output: Symbol(Hello)
console.log(_newSymbols2.description); //output: Hello

Use JavaScript Symbol as object keys

As of today, the JavaScript object property keys can be strings or symbols. Moreover, an object having a Symbol type of property will not be listed when you try to enumerate the object keys. Thus, in my opinion, it looks hidden when you enumerate but not exactly when you use the []token.

See the examples below:

JavaScript
const customerSymbol = Symbol("Object date created");

let customer = {
    name: "Jin Vincent Necesario",
    [customerSymbol]: new Date()
};

console.log(customer); 

Output:

Image 1

Let's try to enumerate by using the for-in loop

JavaScript
for (const key in customer) {
    if (customer.hasOwnProperty(key)) {
        console.log(`customer.${key} is equals to ${customer[key]}`);
    }
}
//output: customer.name is equals to Jin Vincent Necesario
//Note: The symbol-key didn't appear to be part of the object

Directly Access the Symbol Property

However, we can access that contains the symbol via [] token.

JavaScript
console.log("customer[customerSymbol] is equals to " + customer[customerSymbol].getFullYear());
//output: customer[customerSymbol] is equals to 2020

But, of course, there's another way to access the Symbols directly by the use of Object.getOwnPropertySymbols() method.

JavaScript
console.log(Object.getOwnPropertySymbols(customer));

Output:

Image 2

The Symbol.for Method

Basically, the Symbol object maintains a registry of the key/value, where the key is the description, and the value is the symbol. Now, when using a Symbol.for method, it gets added to the registry and the method returns the symbol. Thus, if we try to create a symbol with an existing description, then it will be retrieved.

JavaScript
//create a symbol using for method
const mySymbolFor = Symbol.for("My Unique Description");

let product = {
    name: "Toyota",
    [mySymbolFor]: "Toyota Hilux G"
};

const mySymbolFor2 = Symbol.for("My Unique Description");

console.log(mySymbolFor === mySymbolFor2); //output:true    

Preventing Property-name Collisions

Now, you have gone this far. You might actually be getting your hands dirty with JavaScript Symbol. And, you might be asking: "What's the benefit?".

Actually, they are useful in situations where libraries want to add properties to objects without the risk of having the name collisions.

Summary

  • Symbols are invoked with the use of Symbol() function when you try to use a new instance an error will be thrown.
  • JavaScript Symbols are always unique.
  • Symbols descriptions are purposely for debugging and having the same description doesn't mean Symbols are equivalent.
  • JavaScript Symbols should be explicitly converted into a string, if you wanted to.
  • JavaScript can be used within an object property to prevent property name collisions.
  • The Symbol.for has a table registry for key-value pair, which retrieves existing symbol description, else creates a new one.

I hope you have enjoyed this article, as I have enjoyed writing it. Stay tuned for more. Until next time, happy programming!

History

  • 31st July, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)