What are symbols and how they can be useful to you

Home Dev What are symbols and how they can be useful to you

The symbol is a new primitive value introduced by ES6. It aims to provide us with unique identifiers. In this article, we explore how it works, in what way it is used in the JavaScript language and how we can benefit from that.

Creating symbols

To create a symbol, we use its constructor.

The function has an optional string parameter that acts as a description.

const symbol = Symbol(‘description’);

console.log(symbol);

Symbol(description)

The significant thing is that even if you use the same description twice, every symbol is unique.

Symbol(‘description’) === Symbol(‘description’);

false

The symbol is a new primitive value and has its own type. We can check it using typeof:

symbol

Converting the symbol type

In the “Looking into assembly code of coercion” article, we explore how we can convert types in Javascript. A big part of it is the implicit conversion that happens when we use values of different types together:

console.log(1 + ” added to “ + 2 + ” equals “ + 3);

1 added to 2 equals 3

Even though other types often converse under the hood, it does not include the symbol type.

const symbol = Symbol(‘Hello’);

symbol + ‘world!’;

Uncaught TypeError: Cannot convert a Symbol value to a string

If you would want to use symbols in such a way, converse them explicitly or use the  description property.

const symbol = Symbol(‘Hello’);

 

console.log(`${symbol.description} world!`);

Hello world!

How to use symbols

Before the introduction of symbols, the object keys could only be strings. Trying to use an object as the key for a property does not give us an expected result.

const key = {};

const myObject = {

  [key]: ‘Hello world!’

};

 

console.log(myObject);

{

  [object Object]: ‘Hello world!’

}

The things are different with symbols. The ECMAScript specification states that we can use them as keys:

property

part of an object that associates a key (either a String value or a Symbol value) and a value

Let’s try to do it!

const key = Symbol();

const myObject = {

  [key]: ‘Hello world!’

};

 

console.log(myObject);

{

  Symbol(): ‘Hello world!’

}

Even if two symbols have the same description, they still don’t collide with each other when we use them as keys:

const key = Symbol(‘key’);

const myObject = {

  [key]: ‘Hello world!’

};

 

console.log(myObject[key] === myObject[Symbol(‘key’)]);

false

It means that we can assign an unlimited number of unique symbols and don’t worry about them evert conflicting with each other.

Accessing the value

Now, the only way to access our value is to use the symbol.

console.log(myObject[key]); // Hello world!

There are certain differences when it comes to iterating through the properties of an object with symbols. The  Object.keysObject.entries, and  Object.entries functions don’t give us access to any values that use symbols – the same goes for a for...in loop. The way to iterate through them is to use the  Object.getOwnPropertySymbols function.

const key = Symbol();

const myObject = {

  [key]: ‘Hello world!’

};

 

Object.getOwnPropertySymbols(myObject)

  .forEach((symbol) => {

    console.log(myObject[symbol]);

  });

Hello world!

Judging by the above, we can conclude that symbols provide some hidden layer under in the object, separate from keys that are strings.

Symbols are unique… most of the time

The way to create a global, not-unique symbol is to use the  Symbol.for function. You need to provide it with a string – it searches the symbol registry for a symbol associated with the given key and returns it if found. If that’s not the case, it creates a new symbol.

const symbol = Symbol.for(‘key’);

console.log(symbol === Symbol.for(‘key’));

true

If you have doubts about a symbol being unique, you can use the  Symbol.keyFor function. It returns the associated key if found.

Symbol.keyFor(

  Symbol.for(‘key’)

);

key

Symbol.keyFor(

  Symbol(‘key’)

);

undefined

Well-known symbols

With the introduction of symbols through the ES6, the language itself incorporates it into some of its mechanisms.

Symbol.toStringTag

With the  Symbol.toStringTag we can change the internal  [[Class]] property of an object that is used when stringifying an object.

const dog = { name: ‘Fluffy’ }

console.log(dog.toString()) // ‘[object Object]’

dog[Symbol.toStringTag] = ‘Dog’;

console.log(dog.toString()) // ‘[object Dog]’

If you would like to know more, look into the Looking into assembly code of coercion for additional information

Symbol.iterator

The  for...of loop makes use of the symbols under the hood. Wit the use of the  Symbol.iterator, ic accesses the values to iterate over.

const array = [‘a’, ‘b’, ‘c’];

 

for(let value of array) {

  console.log(value);

}

const array = [‘a’, ‘b’, ‘c’];

 

let iterator = array[Symbol.iterator]();

let iteration;

 

while(

  !(iteration = iterator.next()).done

){

  console.log(iteration.value);

}

a
b
c

Knowing this, you can override the default value that  Symbol.iterator holds to change the behavior of the  for...of loop.

const array = [1, 2, 3];

array[Symbol.iterator] = function* () {

   let i = 0;

   while(this[i] !== undefined) {

     yield Math.random();

     ++i;

   }

}

 

for(let value of array) {

  console.log(value);

}

0.0523720769432241
0.9489775095218018
0.9041067477874434

The above example uses generators. If you would like to know more about them, check out Demystifying generators. Implementing async/await

Other internal symbols

There are many different symbols that you can use to alter the mechanisms of the language. If you are interested in a complete list, check out the MDN documentation.

Summary

In this article, we’ve covered the Symbol type. There are quite a few ways to use that knowledge: by exploring how symbols work we’ve learned how to modify the JavaScript mechanisms through some of the well-known symbols. By using symbols, we can prevent values from colliding with each other, for example in a way that it happened with the MooTools library: if you need to modify the built-in prototypes like the String and Array, it might be a good idea to use Symbols for that. Since symbols are quite an interesting part of the JavaScript language, it is worth trying out.

Leave a Reply

Your email address will not be published.