JavaScript Symbol
Tags: tutorial, javascript, webdev, codenewbie
Published: 2021-06-21 20:02:43

In JavaScript, the object key can only be in either string or symbol. 

> A symbol represents a unique identifier

To create a symbol, the syntax is shown below:

```
id = Symbol()
```

To create a symbol with a description (symbol-name), the syntax is shown below:

```
id = Symbol("description")
```

The description is just a label that is unique to an object.

It is important to note that symbols with the same description are still different.

See the example below:

```js
const id1 = Symbol("description");
const id2 = Symbol("description");

console.log(id1 === id2); // false
```

It is also important to note that symbols do not allow auto-conversion (coercion) to string.

See the example below:

```js
const id3 = Symbol("description");
alert(id3); // TypeError...
```

To do the conversion, use the `toString()` function on it.

See the example below:

```js
const id4 = Symbol("id");
alert(typeof id4.toString); // string
```

Alternatively, we can use the `id.description` to show the description only.

```js
let id5 = Symbol("id");
alert(id5.description, toString id5.description); // id string
```

---
## Hidden Properties
Symbols allow us to create hidden properties of an object.
See the example below:

```js
const person = { // belongs to another code
  name: "Bello"
};

let id = Symbol("id");

person[id] = 4; // added id key to user object

alert( person[id] ); // 4 => accessed data by the symbol as the key
```

The code above shows that a symbol cannot be accessed accidentally by any part of your code. 

If a string is used in place of a symbol, the last string "id" will be overridden (overwritten) by any other previous string id from our script or another JavaScript library script.

See the example below:

```js
const person = { name: "John" };

// my script uses "id" property
person.id = "id value before the last script";

// library script uses the "id" property
person.id = "id value in last script" // overwritten by another script!
console.log(person.id); // id value in last script
```

---
## Symbol id as key

To use a symbol as a key in an object literal, the square bracket must be used around it.

```js
const id = Symbol("id");

const user = {
  name: "John",
  [id]: 639 // not "id": 639
};
```

---
## Cloning symbol keys
The for...in skips any symbol key in an object. 
See the example below:

```js
const id = Symbol("id");
const user = {
  name: "Bello",
  age: 27,
  [id]: 396
};

for (let key in user) {
  console.log(key); // name, age => no symbols
}
// Object.keys(user) also skips them.
```

The `Object.assign` copies both string and symbol properties.

See the example below:

```js
const id = Symbol("id");
const user = {
  name: "Bello",
  age: 27,
  [id]: 396
};

let clone = Object.assign({}, user);
alert( clone[id] ); // 396
```

---
## Global Symbol Registry
Symbols are always different by default even if they have the same description, but sometimes we want to use the same-named symbol of the same entities anyway in a program. 

To achieve that, the `Symbol.for(key)` is used to create a global symbol registry for repeated access by the same name to return exactly the same symbol.

See the example below:

```js
const id1 = Symbol.for("id"); // if the symbol did not exist, it is created
const id2 = Symbol.for("id");

console.log( id1 === id2); // true => the same symbol
```

> Symbols inside the registry are called global symbols.

---
## Symbol.keyFor
The reverse of Symbol.for is Symbol.keyFor, it returns a name by a global symbol.

See the example below:

```js
// get symbol by name
const sym1 = Symbol.for("id1");
const sym2 = Symbol.for("id2");

// get name by symbol
console.log( Symbol.keyFor(sym1) ); // id1
console.log( Symbol.keyFor(sym2) ); // id2
```

> The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. If the symbol is not global, it returns `undefined`

See the example below:

```js
const globalSymbol = Symbol.for("globalName");
const localSymbol = Symbol("localName");

console.log( Symbol.keyFor(globalSymbol) ); // globalName => global symbol
console.log( Symbol.keyFor(localSymbol) ); // undefined => not global

console.log( localSymbol.description ); // localName
```

---
## System Symbols
Internally, there are different JavaScript System Symbols. 
Below is a few of them.

- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.iterator
- Symbol.toPrimitive

Check out the full list on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#static_properties)`