ES6 – Symbol

 · 5 mins read

What is Symbol?

The data type “symbol” is a primitive data type having the quality that, values of this type can be used to make object properties that are anonymous.

This data type is used as the key for an object property when the property is intended to be private, for the internal use of a class or an object type. The symbol data type is highly specialized in purpose, and remarkable for its lack of versatility; an instance of Symbol can be assigned to an L-value, it can be examined for identity, and that’s all; no other operators apply.

A value having the data type “symbol” can be referred to as a “symbol value.” In the JavaScript run-time environment, a symbol value is created by invoking the function

Symbol()

which dynamically produces an anonymous, unique value. The only sensible usage is to store the symbol and then use the stored value to create an object property.

The following example stores the symbol in a “var”.

var  myPrivateMethod  = Symbol();
this[myPrivateMethod] = function() {...};

Feature:

When a symbol value is used as the identifier in a property assignment, the property (like the symbol) is anonymous; and also is non-enumerable. Because the property is non-enumerable, it will not show up as a member in the loop construct “for( … in …)”, and because the property is anonymous, it will not show up in the result array of “Object.getOwnPropertyNames()”.

The property can be accessed by using the original symbol value that created it, or by iterating on the result array of “Object.getOwnPropertySymbols() “. In the prior code example, access to the property will be through the value that was stored in the myPrivateMethod variable.

Attention:

The built in function “Symbol()” is an incomplete class that returns a symbol value when called as a function, that throws an error upon attempts to use it as a constructor with the syntax “new Symbol()”, that has static methods for accessing JavaScript’s global symbol table, and that has static properties for addressing certain symbols that are present in commonly used objects.

The methods that access the global symbol registry are “Symbol.for()” and “Symbol.keyFor()”

The method Symbol.for(“tokenString”) returns a symbol value from the registry, and Symbol.keyFor(symbolValue) returns a token string from the registry; each is the other’s inverse, so the following is true:

Symbol.keyFor(Symbol.for("tokenString"))=="tokenString";  // true

Purpose

The Symbol() function and the symbol values it creates might be useful to programers designing a custom class. Symbol values provide a way by which custom classes can create private members, and maintain a symbol registry that pertains just to that class. A custom class can use symbol values to create “own” properties that are shielded from unwanted, casual discovery. Within the class definition, the dynamically created symbol value is saved to a scoped variable, available only privately within the class definition. There is no token string; the scoped variable plays the equivalent role of a token.

Symbol type is a new feature in ECMAScript 2015 and there is no ECMAScript 5 equivalent for symbol.

Others

The typeof operator can help you to identify symbols.

typeof Symbol() === 'symbol'
typeof Symbol('foo') === 'symbol'
typeof Symbol.iterator === 'symbol'

Some things to note when working with type conversion of symbols.

  • When trying to convert a symbol to a number, a TypeError will be thrown

    (e.g. +sym or sym0).
  • When using loose equality, Object(sym) == sym returns true.
  • Symbol(“foo”) + “bar” throws a TypeError (can’t convert symbol to string). This prevents you from silently creating a new string property name from a symbol, for example.
  • The “safer” String(sym) conversion works like a call to Symbol.prototype.toString() with symbols, but note that new String(sym) will throw.

Properties

Symbol.length

Length property whose value is 0.

Symbol.prototype

Represents the prototype for the Symbol constructor.

Built-in symbols

In addition to your own symbols, JavaScript has some built-in symbols which represent internal language behaviors which were not exposed to developers in ECMAScript 5 and before. These symbols can be accessed using the following properties:

Iteration symbols

  • Symbol.iterator

    A method returning the default iterator for an object. Used by for…of.</p>

  • Symbol.asyncIterator

    A method that returns the default AsyncIterator for an object. Used by for await of.

Regular expression symbols
  • 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.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().

Other symbols
  • 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.unscopables

    An object value of whose own and inherited property names are excluded from the with environment bindings of the associated object.

  • 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().


Examples

Symbol.hasInstance

class Even {
  static [Symbol.hasInstance](obj) {
    return Number(obj) % 2 === 0;
  }
}

// equal to this:
const Even = {
  [Symbol.hasInstance](obj) {
    return Number(obj) % 2 === 0;
  }
};


1 instanceof Even // false
2 instanceof Even // true
12345 instanceof Even // false

Symbol.replace

String.prototype.replace(searchValue, replaceValue)
// equal to 
searchValue[Symbol.replace](this, replaceValue)
const x = {};
x[Symbol.replace] = (...s) => console.log(s);

'Hello'.replace(x, 'World') // ["Hello", "World"]

LINKS:

symbol

glossary-symbol

ECMAScript 6 Symbol