Modern JavaScript: Symbol Basics
Welcome to the Symbol Basics lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
Normally, object keys are strings. When an object has the key
'name', we can access it withobj.nameor withobj['name'].>
const obj = {name: 'Amir'};obj['name'];Result:
'Amir'
Most JavaScript data types can't be used as object keys. For example, if we try to use
trueas a key, it gets converted into the string'true'.>
const obj = {};obj[true] = 1;Object.keys(obj);Result:
If an object already has the key
'true', and we try to addtrueas a key, we'll end up overwriting the value that already exists at'true'. The object will still only have one'true'key at the end.>
const obj = {'true': 1};obj[true] = 2;obj;Result:
{true: 2}Modern versions of JavaScript have alleviated this limitation by adding symbols. Symbols are a new data type that can be used in object keys. We'll begin by exploring the basics of how symbols work, then move on to using them as keys.
We can define a symbol by giving it a description:
Symbol('name')orSymbol('dataIsSynced'). The description should say what the symbol is used for.>
Symbol('name').description;Result:
'name'
Symbol equality works like array equality. A given array is always equal to itself. Likewise, a given symbol is always equal to itself.
>
const catArray = ['cat'];catArray == catArray;Result:
true
>
const dogArray = ['dog'];dogArray === dogArray;Result:
true
>
const horseSymbol = Symbol('horse');horseSymbol == horseSymbol;Result:
true
>
const pigSymbol = Symbol('pig');pigSymbol === pigSymbol;Result:
true
Two arrays are never equal to each other, even if they contain the same elements. Likewise, two symbols are never equal to each other, even if they have the same description.
>
['cat'] == ['cat'];Result:
false
>
['dog'] === ['dog'];Result:
false
>
Symbol('cat') == Symbol('dog');Result:
false
>
Symbol('horse') === Symbol('cow');Result:
false
>
Symbol('cat') == Symbol('cat');Result:
false
>
Symbol('dog') === Symbol('dog');Result:
false
>
const symbol1 = Symbol('cat');const symbol2 = Symbol('cat');[symbol1 === symbol1, symbol1 === symbol2, symbol2 === symbol2];Result:
[true, false, true]
Now that we've seen the basics of symbols, we can start using them as object keys. But how exactly do we get a symbol key into an object? If we store it in a
nameSymbolvariable and write{nameSymbol: 1}, then the unquotednameSymbolkey is just a string. The key is'nameSymbol'and thenameSymbolvariable isn't referenced at all.>
const nameSymbol = Symbol('name');const obj = {nameSymbol: 1};Object.keys(obj);Result:
To use the symbol itself as a key, we can use computed property syntax:
{[nameSymbol]: ...}. Then, to access a symbol key, we can douser[nameSymbol]. (Trying to access it withuser.nameSymbolwould have the same problem as before: it would look up the value at the string key'nameSymbol'.)Be careful in these next examples: we intentionally mix up symbols and strings.
>
// For reference: accessing a key that doesn't exist gives undefined.const user = {};user.propertyThatDoesntExist;Result:
>
const nameSymbol = Symbol('name');const user = {[nameSymbol]: 'Amir'};user[nameSymbol];Result:
'Amir'
>
const nameSymbol = Symbol('name');const user = {[nameSymbol]: 'Amir'};user.nameSymbol;Result:
undefined
>
const nameSymbol = Symbol('name');const user = {nameSymbol: 'Amir'};user[nameSymbol];Result:
undefined
Symbol descriptions are usually strings, so it's tempting to think of symbols as just a special kind of string. But that's a mistake! Here's an example of why:
We can use the string
'name'as an object key. We can also use the symbolSymbol('name')as an object key. An object can have both of those keys at once, with each key holding a different value!>
const nameString = 'name';const nameSymbol = Symbol('name');const user = {[nameString]: 'Amir',[nameSymbol]: 'Betty'};[user['name'], user[nameSymbol]];Result:
['Amir', 'Betty']
The example above hints at why symbols exist. They allow us to add properties to objects without affecting the "normal" properties. We'll see examples of that in future lessons.