JavaScript Symbol Types

In general, object property keys can be of two types: string and symbol. Symbols are ultimately unique identifiers. They can be created by using the factory function Symbol().

For instance:

javascript symbol

After creating a symbol, you can give it a name or a description. It is especially useful for debugging practices. Let’s check out the following example:

//  id is a symbol, it's a description "id"
let id = Symbol("id");

As we have already noted, symbols are unique. Even when you create a variety of symbols with the same name, they are considered different symbols.

Remember that descriptions and names are merely labels not affecting anything.

Here is an example:

w3docs logo Javascript symbol type
let mySymbol1 = Symbol("mySymbol"); let mySymbol2 = Symbol("mySymbol"); console.log(mySymbol1 == mySymbol2); // false

In the case above, the two symbols have the same description, but they are not equal.

It’s important to know that it’s not possible to auto-convert symbols to a string.

For example, this alert will bring an error:

w3docs logo Javascript symbol type
let mySymbol = Symbol("mySymbol"); console.log(mySymbol); // TypeError: Cannot convert a Symbol value to a string

For showing a symbol, you need to explicitly call .toString() on it, as follows:

w3docs logo javascript symbol type
let mySymbol = Symbol("mySymbol"); console.log(mySymbol.toString()); // Symbol(mySymbol), now it works

For getting symbol.description property, call:

w3docs logo Javascript symbol description
let mySymbol = Symbol("mySymbol"); console.log(mySymbol.description); // mySymbol

About “Hidden” Properties

With the help of symbols, you can easily create the so-called “hidden” properties of an object. It is impossible to access or overwrite other parts of the code.

In case you work with site objects belonging to third-party code, you will need to add identifiers to them. It is necessary to use a symbol key for it, as follows:

w3docs logo Javascript symbol key
let site = { // belongs to another code name: "W3Docs" }; let id = Symbol("id"); site[id] = 1; console.log(site[id]); // we can access the data using the symbol as the key

In another case, when another script wants to have its identifier inside the site.

It might be another JavaScript library so that the scripts are unaware of one another.

So, that script may create its Symbol("id").

For instance:

// ...
let id = Symbol("id");
site[id] = "Their id value";

Symbols in a Literal

For using a symbol in an object literal, it is necessary to insert square brackets around it.

Just look at this example:

w3docs logo Javascript symbol
let id = Symbol("id"); let site = { name: "W3Docs", [id]: 100 // not "id: 100" }; console.log(site[id]);

This is because you need the value from the variable, id as the key but not the string “id”.

The for…in Skips Symbols

The loop doesn’t involve symbolic properties. Here is an example:

w3docs logo Javascript symbol loop
let id = Symbol("id"); let site = { name: "W3Docs", [id]: 10 }; for (let key in site) { console.log(key); // name , no symbols } console.log("Direct: " + site[id]); // works the direct access by the symbol

Global Symbols

As we have already mentioned, symbols are unique, even if they have the same description. But, sometimes, you may need the symbols with the same name to be the same entities. For example, various parts of your application wish to access the symbol "id" which means the same property.

A global symbol registry is there to achieve that. It allows creating symbols inside of it and accessing them later. Moreover, it ensures that continuous accesses by the same name show precisely the same symbol. For reading a symbol for the global registry, you are recommended to use Symbol.for(key).

Using this call helps to check the global registry. Then, if there is a symbol, defined as key, it will be returned. Otherwise, a new symbol Symbol(key) will be created and stored in the registry by a particular key.

It is demonstrated in the example below:

w3docs logo Javascript symbol.for the global registry
// read from the global registry let id = Symbol.for("id"); // if this the symbol did not exist, it's created // read it again let idAgain = Symbol.for("id") // the same symbol console.log(id === idAgain); // true

The symbols that are inside the registry are known as global symbols. You can use them at the time you want an application-wide symbol that has an entry everywhere in the code.


It is possible to use a reverse call for global symbols. You can do that with the help of Symbol.keyFor(sym). It will do the reverse: return a name by a global symbol.

For better understanding, check out the following example:

w3docs logo Javascript global symbol
// get symbol by name let sym1 = Symbol.for("siteName"); let sym2 = Symbol.for("id"); // get name by symbol console.log(Symbol.keyFor(sym1)); // siteName console.log(Symbol.keyFor(sym2)); // id

The Symbol.keyFor will work exclusively for global symbols. In case the symbol turns out not global, there will be no option for finding it and returning undefined. In other words, each symbol has a description property.

For example:

w3docs logo Javascript symbol description
let globalSymbol = Symbol.for("name"); let localSymbol = Symbol("name"); console.log(Symbol.keyFor(globalSymbol)); // name, global symbol console.log(Symbol.keyFor(localSymbol)); // undefined, not global console.log(localSymbol.description); // name

System Symbols

Internally JavaScript uses a wide range of system symbols.

Here are some of them:

  1. Symbol.hasInstance
  2. Symbol.iterator
  3. Symbol.isConcatSpreadable
  4. Symbol.toPrimitive

There are many other system symbols, as well.

For instance, Symbol.toPrimitive is targeted at describing the object to primitive conversion.

Symbol.isConcatSpreadable can be described as a pretty specific symbol. It drives the behavior of Array#concat..


In JavaScript, symbols guarantee access level uniqueness to objects. All developers need to have a basic understanding of symbols and their use cases.

Technically, symbols are not entirely hidden. A built-in method Object.getOwnPropertySymbols(obj) will allow you to receive all the symbols. There exists another method, called Reflect.ownKeys(obj),, which is targeted at returning all the keys of an object along with symbolic ones. Anyway, most libraries, syntax constructs, and built-in functions avoid using the methods mentioned above.

Do you find this helpful?