JavaScript Symbol Type: A Complete Guide

JavaScript Symbol Type: A Complete Guide

Hey, friends👋🏼

hello.gif (180×200)

I am Aryan Sharma and I hope you all are doing great!

This is another blog in the JavaScript course for absolute beginners.

So, I am starting this blog.

Let's get started!!


Symbol

Symbol is a built-in object whose constructor returns a symbol primitive.

A symbol represents a unique identifier.

A value of this type can be created using Symbol()

let name = Symbol();

We can also give them description, basically these are used for debugging purposes while coding.

let name = Symbol("name");

A unique thing with symols is that:

  • Even if we create many symbols with same description, they are different values.

  • Thay are always unique.

let name1 = Symbol("name");
let name2 = Symbol("name");

alert(name1 == name2); // false

Application of Symbols

Symbols are used while coding having various conditions.

  • Symbols don’t auto-convert to a string.

    Most values in JavaScript support implicit conversion to a string. For instance, we can alert almost any value, and it will work. Symbols are special. They don’t auto-convert.

    For instance, this alert will show an error

      let id = Symbol("id");
      alert(id); // TypeError: Cannot convert a Symbol value to a string
    

    That is a "language guard" against errors, because strings and symbols are essentially distinct and should not be unintentionally converted into each other.

  • If we really want to show a symbol, we need to explicitly call .toString() on it, like here:

      let id = Symbol("id");
      alert(id.toString()); // Symbol(id), now it works
    

    Or get symbol.description property to show the description only:

      let id = Symbol("id");
      alert(id.description); // id
    

Unknown properties

There are some unknown properties of symbol that we know.

Hidden Properties

Symbols allows us to create hidden properties of an object, that no other part of code can accidentally access or overwrite.

For instance, if we’re working with user objects, that belong to a third-party code. We’d like to add identifiers to them.

Let’s use a symbol key for it:

let user = { // belongs to another code
  name: "John"
};

let id = Symbol("id");

user[id] = 1;

alert( user[id] );

You might be wondering about why do we use Symbol("id") and not id?🤔

As such, Symbol("id") cannot be accessed by 3rd party variables, so we are at no-risk from those variables which are predefined from that library or package.

Symbols in an object literal

To use a symbol in an object literal {...}, we need square brackets around it.

Example:

let id = Symbol("id");

let user = {
  name: "Aryan",
  [id]: 123 // not "id": 123
};

id here, is the key and not a string.

Symbols in for...in

Symbolic properties do not act in for..in loop. They do not have any effect on for...in and can't be accessed simply.

let id = Symbol("id");
let user = {
  name: "Aryan",
  age: 19,
  [id]: 123
};

for (let key in user) alert(key); // name, age (no symbols)

It can acceessed by:


alert( "Hey " + user[id] ); // Hey 123

Global symbols

Normally, symbols have different shapes or designs, even if they share the same name. But sometimes, we want symbols with the same name to represent the same thing.

For example, different parts of our application might need to use the symbol "id" to refer to the exact same property or information.

To make this happen, we use something called a global symbol registry.

This registry allows us to create symbols and then retrieve them later. Importantly, it ensures that if we ask for a symbol with the same name multiple times, we'll always get the exact same symbol.

To get or create a symbol in the registry, you can use the function Symbol.for(key).

That call checks the global registry, and if there’s a symbol described as key, then returns it, otherwise creates a new symbol Symbol(key) and stores it in the registry by the given key.

For instance:

// read from the global registry
let id = Symbol.for("id"); // if the symbol did not exist, it is created

// read it again (maybe from another part of the code)
let idAgain = Symbol.for("id");

// the same symbol
alert( id === idAgain ); // true

Symbol.keyFor

We've seen that for global symbols, Symbol.for(key) provides a symbol by name.

To accomplish the inverse and retrieve a name by global symbol, we may use: Symbol.keyFor(sym)

// get symbol by name
let sym1 = Symbol.for("name");
let sym2 = Symbol.for("id");

// get name by symbol
alert( Symbol.keyFor(sym1) ); // name
alert( Symbol.keyFor(sym2) ); // id

The Symbol.keyFor internally uses the global symbol registry to look up the key for the symbol. So it doesn’t work for non-global symbols. If the symbol is not global, it won’t be able to find it and returns undefined.

That said, all symbols have the description property.

let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");

alert( Symbol.keyFor(globalSymbol) ); // name
alert( Symbol.keyFor(localSymbol) ); // undefined

alert( localSymbol.description ); // name

System symbols

Several pre-defined system symbols that JavaScript uses in internal working.

Some are :-

  • Symbol.hasInstance

  • Symbol.isConcatSpreadable

  • Symbol.iterator

    And there we reach at the end of this blog...

I hope you loved this blog💖

Thanks for supporting

Have a good day my friend

Follow this blog!