what is symbol used for in JavaScript

  1. What is symbol?
  2. Use cases
    1. 1.Used as an identifier for object properties
    2. 2. Enable private properties.
  3. Predefined Symbols

A new primitive data type was introduced in ES2015 - Symbol. It’s relative new, you might not be familiar with it yet.

In this article we will explain what a Symbol is and how it can be used in real life apps.

What is symbol?

The data type symbol is a primitive data type, it is one of JavaScript’s 6 primitive data types: string, number, boolean, undefined, bigint and symbol.

There is a Symbol() function available, it returns a value of type symbol. Every value returned is unique, you can never create two identical values, even though calling this function with the same parameter.

Symbol can accept an optional description as parameter, but only for debugging purpose.

1
2
3
4
5
6
7
8
9
10
11
12
13
const symbol1 = Symbol();
const symbol2 = Symbol();
const symbol3 = Symbol('foo');
const symbol4 = Symbol('foo');

console.log(typeof symbol1); // "symbol"

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

console.log(symbol3 === symbol4); // false

// Use the description property to get the its description.
console.log(symbol3.description); // "foo".

In case you want to get an already created symbol, you can use Symbol.for() method. This method creates a symbol available in a global symbol registry list if the given key was not found, otherwise the existing one was returned.

1
2
3
4
5
6
7
8
9
10
11
12
13
Symbol.for('a'); // create a new global symbol
Symbol.for('a'); // retrieve the already created symbol

console.log(Symbol.for('bar') === Symbol.for('bar'));
// expected output: true

console.log(Symbol('bar') === Symbol('bar'));
// expected output: false

const symbol1 = Symbol.for('foo');

console.log(symbol1.toString()); // "Symbol(foo)"
console.log(Symbol.for('foo') === symbol1); // true

Use cases

1.Used as an identifier for object properties

By using symbols, you don’t need to worry about key collisions in objects, this is the data type’s primary purpose.

1
2
3
4
5
6
7
8
9
10
11
12
let thirdPartyObject = {
prop1: '3rd party prop1'
};

thirdPartyObject[Symbol('prop1')] = 'changed';
console.log(thirdPartyObject);
// {prop1: "3rd party prop1", Symbol(prop1): "changed"}

// Others may try to add their own prop1 attribute
thirdPartyObject[Symbol('prop1')] = 'changed again';
console.log(thirdPartyObject);
// {prop1: "3rd party prop1", Symbol(prop1): "changed", Symbol(prop1): "changed again"}

2. Enable private properties.

The original motivation for introducing symbols is to enable private properties in JavaScript.

Symbols are not enumerable in for…in iterations.

1
2
3
4
5
6
7
8
9
10
let obj = {}

obj[Symbol('a')] = 'a'
obj[Symbol.for('b')] = 'b'
obj['c'] = 'c'
obj.d = 'd'

for (let i in obj) {
console.log(i) // logs "c" and "d"
}

Symbol-keyed properties are ignored when using JSON.stringify() as well:

1
2
JSON.stringify({[Symbol('foo')]: 'foo'})
// '{}'

However, they are not 100% hidden, you can still get these properties, use Object.getOwnPropertySymbols() or Reflect.ownKeys():

1
2
3
4
5
6
7
8
9
10
let obj = {}

obj[Symbol('a')] = 'a'
obj[Symbol.for('b')] = 'b'
obj['c'] = 'c'
obj.d = 'd'

console.log(Reflect.ownKeys(obj)); // ["c", "d", Symbol(a), Symbol(b)]

console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(a), Symbol(b)]

Predefined Symbols

It has several properties that expose several members of built-in object. These are predefined symbols, they are also called well-known symbols.

  • Symbol.asyncIterator - A method that returns the default AsyncIterator for an object. Used by for await…of.
  • Symbol.hasInstance - A method determining if a constructor object recognizes an object as its instance. Used by instanceof.
  • Symbol.isConcatSpreadable - A Boolean value indicating if an object should be flattened to its array elements. Used by Array.prototype.concat().
  • Symbol.iterator - A method returning the default iterator for an object. Used by for…of.
  • Symbol.match - A method that matches against a string, also used to determine if an object may be used as a regular expression. Used by String.prototype.match().
  • Symbol.matchAll - A method that returns an iterator, that yields matches of the regular expression against a string. Used by String.prototype.matchAll().
  • Symbol.replace - A method that replaces matched substrings of a string. Used by String.prototype.replace().
  • Symbol.search - A method that returns the index within a string that matches the regular expression. Used by String.prototype.search().
  • Symbol.split - A method that splits a string at the indices that match a regular expression. Used by String.prototype.split().
  • Symbol.species - A constructor function that is used to create derived objects.
  • Symbol.toPrimitive - A method converting an object to a primitive value.
  • Symbol.toStringTag - A string value used for the default description of an object. Used by Object.prototype.toString().
  • Symbol.unscopables - An object value of whose own and inherited property names are excluded from the with environment bindings of the associated object.