Close

JavaScript - Symbol Type

[Updated: Nov 23, 2018, Created: Nov 12, 2018]

Symbol is a new immutable primitive data type in JavaScript ES6.

Creating Symbol

It can be created by calling Symbol() function:

let s = Symbol();
console.log(s.toString());
console.log(typeof s)
console.log(typeof s === 'symbol')

Symbol cannot be converted to strings implicitly like in alert() or console.log():

let s = Symbol();
console.log(s)

Symbol can also be created by passing a description (description does not serve any real purpose other than to be used in debugging):

let s = Symbol("my symbol");
console.log(s.toString())

s = Symbol(10);
console.log(s.toString())

s = Symbol(new Date());
console.log(s.toString())

Symbols are unique

Two symbols can never be the same:

let s1 = Symbol("my symbol");
let s2 = Symbol("my symbol");
console.log(s1 === s2)

What is the use of Symbols?

Using Symbol as object property name

Symbol can be used as an identifier for object properties:

let id = Symbol();
let employee = {};
employee[id] = 10;
employee['name'] = 'Mike';
console.log(employee[id]);
console.log(employee); //id ignored

Symbol key/value is ignored when we print the object (like above example). It is also ignore in for-in loop:

let id = Symbol();
let employee = {};
employee[id] = 10;
employee['name'] = 'Mike';
for (let k in employee) {
    console.log(k);
}

So Symbol identifier can be used for some hidden properties.

They are also ignored by JSON.stringify():

let id = Symbol();
let employee = {};
employee[id] = 10;
employee['name'] = 'Mike';
let json = JSON.stringify(employee);
console.log(json);

When Symbol is used as a key in object literal then we need to use square brackets (also see ES6 object literal changes):

let id = Symbol();
let employee = {
    [id]: 10, name: 'Mike' };
console.log(employee);

Using Symbol as method/function name

Symbol can also be used as the name of a method:

let compare = Symbol();
class Math {
    constructor() {
        this.desc = "math utility";
    }
    //a method
    [compare](x, y) {
        return x === y ? 0 : x < y ? -1 : 1;
    }
}

let math = new Math();
console.log(math);
let doCompare = math[compare];
let result = doCompare(7, 5);
console.log(result);

Using symbol method name in Object literal syntax:

let compare = Symbol();
let math = {
    desc: 'math utility',
    [compare](x, y) { return x === y ? 0 : x < y ? -1 : 1; } //using ES6 shorthand method syntax
};
console.log(math);
let result = math[compare](5, 7);
console.log(result);
let compare = Symbol();
let math = {
    desc: "math utility",
    [compare]: function(x, y) { return x === y ? 0 : x < y ? -1 : 1; } //using function syntax
};
console.log(math);
let result = math[compare](5, 7);
console.log(result);

Sharing symbols via a global registry

Symbols can also be created by using function Symbol.for(key). In this case they are kept in a global symbol registry.
For a given key if symbol already exits it is returned otherwise a new one is created, stored in the registry and returned:

let s1 = Symbol.for("test"); // new symbol created, stored with key 'test' and returned
let s2 = Symbol.for("test"); // as symbol with key 'test' already exits it is returned
console.log(s1 == s2);

Symbols created this way are available through out the application, even across different files.

Another method Symbol.keyFor(symbolInstance) can be used to get the Symbol's key:

let s = Symbol.for("test"); //global
let k = Symbol.keyFor(s);
console.log(k);

let s2 = Symbol("myDesc"); //not global
let k2 = Symbol.keyFor(s2);
console.log(k2);

Built-in symbol

JavaScript uses various built-in symbols internally which are also available to the developers since ES6.

See Also