Language: EN

javascript-tipo-symbol

The Symbol Type in JavaScript

A Symbol is a primitive data type in JavaScript that represents a unique and persistent identifier.

Unlike other primitive data types like number, string, or boolean, symbols are always unique.

This means that every time you create a new symbol, you get a distinct value that cannot be duplicated.

  • Uniqueness: Each Symbol is unique and immutable, meaning that two symbols will never be equal.
  • Non-enumerability: Properties of type Symbol are not enumerable by default, meaning they will not appear in operations like for...in.

The Symbol data type is one of the most advanced and least understood types, but it offers useful features in certain contexts.

Creating a Symbol

To create a Symbol, you simply use the constructor function Symbol() without the new keyword.

const mySymbol = Symbol();

In this example, id is a new unique and immutable Symbol.

Description of a Symbol

It is possible to provide an optional description when creating a Symbol. This description can be useful for identifying the purpose of the Symbol.

const name = Symbol('Symbol name');

In this case, name is a Symbol with an optional description.

The description of a symbol does not affect its uniqueness, but it can be useful for debugging.

let symbol = Symbol('my symbol');
console.log(symbol.toString()); // Prints: Symbol(my symbol)

The description can be obtained through the toString() method of the symbol.

Uniqueness of Symbols

The main characteristic of symbols is that their value is always unique and different from all others (even if two symbols have the same description).

let symbol1 = Symbol('description');
let symbol2 = Symbol('description');

console.log(symbol1 === symbol2); // Prints: false

In the previous example,

  • symbol1 and symbol2 are two distinct symbols, even though both have the same description.
  • This means that each call to Symbol() has produced a unique identifier.

Uses of the Symbol Type

Preventing Property Overwrites

One of the most common uses of Symbols is as keys for object properties, to prevent them from being accidentally overwritten.

Let’s see it with an example.

let object = {
  property: 'value 1'
};

// Later, another part of the code adds a property with the same name:
object.property = 'value 2';

console.log(object.property);  // Prints: 'value 2'

In this case,

  • We have defined a literal object, with the property having the value value 1
  • Subsequently, someone accidentally overwrites it with the value value 2
// We create a Symbol with a description
let symbolProperty = Symbol('property');

let object = {};

// We use the Symbol as a key for the property
object[symbolProperty] = 'value 1';

// Later, we try to add another property with the same name,
// but since we used a Symbol, there is no overwrite
let anotherSymbol = Symbol('property');
object[anotherSymbol] = 'value 2';

// We access the properties using the Symbols
console.log(object[symbolProperty]);  // Prints: 'value 1'
console.log(object[anotherSymbol]);       // Prints: 'value 2'

In this example,

  • We create a Symbol called symbolProperty and use it as a key for a property in the object.
  • Then, in another part of the code, we create a new Symbol called anotherSymbol. Even though both symbols have the same description (‘property’), they are different from each other.
  • Therefore, when we assign 'value 2' to object[anotherSymbol], it does not overwrite the value of object[symbolProperty], but rather creates a new property.

Symbol Methods and Properties

JavaScript includes several built-in symbols that are used as keys for special methods and properties. These symbols are defined in the Symbol object.

SymbolDescription
Symbol.iteratorThis symbol is used to define the iterator of an object.
Symbol.toStringTagThis symbol is used to define the value of the Symbol.toStringTag property

Symbol.toStringTag is used to customize the result of the Object.prototype.toString() method.

Global Symbols with Symbol.for()

Another different use of Symbols occurs with the Symbol.for() method. This allows you to create a global symbol that is accessible throughout the execution environment.

If you try to create a symbol with the same key, it will return the same symbol. In other words, Symbol.for() maintains a kind of “global registry” of symbols.

const globalSymbol1 = Symbol.for('mySymbol');
const globalSymbol2 = Symbol.for('mySymbol');

console.log(globalSymbol1 === globalSymbol2); // Prints: true

In this case,

  • We create a global symbol with the key 'mySymbol' using Symbol.for('mySymbol').
  • When calling Symbol.for('mySymbol') again, JavaScript does not create a new symbol.
  • Instead, it looks in the global symbol registry, and if a symbol with that key (like 'mySymbol') already exists, it returns the same symbol.
  • Since they are the same symbol, the comparison globalSymbol1 === globalSymbol2 returns true.

This is different from creating symbols with Symbol(), which always generates a unique symbol, even if you use the same description.

In contrast, Symbol.for() ensures that the created symbol is unique at the global level, and if a symbol with that key already exists, it will return the same symbol.

Practical Examples