ES6 introduced a new primitive data type to JavaScript. What differentiates symbols from pre-ES6 primitive data types (string, number, boolean, null, undefined) is their uniqueness — Every symbol value is guaranteed to be one-of-a-kind. Just like the Number, String, and Boolean primitives, Symbols have a Symbol function which can be used to create them.

Here’s a situation where Symbols can be useful. For example, you are creating an object ‘fruit’ that looks something like this :

const fruit = {  
	'book’: 	{ color: 'red’ },

        'pen’: 	{ color: 'yellow’ },

	'pencil’: 	{ color: 'orange’ }
};

Now suppose you want to add another property named ‘banana’. See the problem? You could do something like pen1, pen2, and so on..But that is not very elegant. This problem is solved by symbols. You can define two symbols like this:

const sym2 = Symbol('pen');

const sym3 = Symbol('pen');

console.log(sym2 === sym3);

Notice that both symbols have the same description but the output of the console statement returns false! The string is optional and is not used to access the symbol itself.

Syntax:

var name = Symbol();

Never create symbol by using new keyword it will throws error.

var name = new Symbol();// throws error

Symbols have “description”

var mySymbol = Symbol('some text');//here 'some text' is description

By default, each new Symbol has a unique value. When you create a symbol it creates a new value. If you don’t have the reference for the Symbol, you cannot use it. So, two symbols will never equal the same value, even if they have the same description.

var hello = Symbol(‘Sachin’);

var hi = Symbol(‘Sachin’);

hello==hi // false

Symbol.for( )

When we want to mutable Symbol then we can do this with the help of    Symbol.for( ) method.

var hello=Symbol.for(‘Sachin’);

var hi=Symbol.for(‘Sachin’);//returns the same symbol

hello==hi//true

Symbols as property keys

Symbols can be used as property keys

var MY_KEY = Symbol();
var obj = {};

obj[MY_KEY] = 123;
console.log(obj[MY_KEY]); // 123

Symbols can be used  as keys on an object. Since symbols are unique, we can add as many properties as we’d like to an object without ever worrying about conflicting keys. Furthermore, since symbol values aren’t directly observable (they all simply return Symbol() in the console), they have an anonymizing effect when used as keys.

To illustrate, let’s create an object with a few properties:

const books = {};

abby['javascript'] = 5;

abby['java'] = 2;

abby['python'] = 1;

Next, we’ll create some symbol values:

const hasBook = Symbol();

const hasPen = Symbol();

Finally, let’s use these symbol values to store some extra data on our object:

books[hasBook] = false;

books[hasPen] = true;
``

Let’s take a look at how our object evaluates in the console:

// javascript: 5

//java: 2

// python: 1

// Symbol(): false

// Symbol(): true

However, this provides slight obscurity at best — It is not a practice that is sufficient to secure private data.

Where we use Symbols:

Use symbols when your requirement is one of these:

  1. Enum: To allow you to define constants with semantic names and unique values.
const directions = {
 UP   : Symbol( ‘UP’ ),
 DOWN : Symbol( ‘DOWN’ ),
 LEFT : Symbol( ‘LEFT’ ),
 RIGHT: Symbol( ‘RIGHT’ )
};

2.  Name Clashes: when you wanted to prevent collisions with keys in objects.

For example, say that you have an object where you are adding a custom toUpperCase to global Array.prototype .

Now, imagine you loaded another library and it had a different version of Array.prototype.toUpperCase. Then your function might break because of name collision.

    var i;
    for(i=0; i<tgis.length;i++)
    {
        this[i]= this.toUpperCase();
    }
    return this;
    }
    var name= ['akanksha', 'gupta'];
    name.toUpperCase() //['AKANKSHA', 'GUPTA']
    ```

3. Privacy: when you don’t want your object properties to be enumerable.

Here are a few things you must keep in mind about Symbols:

  1. All symbols are unique! when you use Symbols in your objects you can rest assured that they will never clash with your String keys.
  2. Symbols cannot be read using existing methods like Object.getOwnPropertyNames(), Object.keys(). To read the symbols within your object ES6 now provides a special method Object.getOwnPropertySymbols()
  3. Symbols are not enumerable, that is, they do not appear in a for..in or a for..of loop
  4. Symbols may not always be unique. There’s a method Symbol.for()that returns a Symbol which isn’t unique. When in doubt, always create your own symbols!
  5. Symbols cannot be typecasted to primitive datatypes. Try something like this and it would throw an error,

console.log(' '+Symbol()); //Error

console.log(Symbol() + 'foo'); //Error

This is to prevent ‘stringifying’ of the symbol.

Some other popular built-in symbols are — Symbol.match, Symbol.replace, Symbol.search, Symbol.split, Symbol.isConcatSpreadable etc

Conclusion:

  • Symbols are a new primitive data type
  • Symbol values are unique
  • Symbol values can be used as keys on an object (instead of string values), and will never conflict with pre-existing keys