šŸŽ Checkout my Learn React by Making a Game course and get 1 month Free on Skillshare!

JavaScript Symbols: an example-driven explanation

I've always struggled to understand what Javascript symbols are, until this weekend when a friend of mine explained them in the context of libraries.

Let's take the following example. We have two Javascript libraries libOne and libTwo. Each library ads a new property to the given object:

const user = {
    age: 29
}

const libOne = (obj) => {
    obj.newProperty = 'Property from LibOne'
}

const libTwo = (obj) => {
    obj.newProperty = function() {
        return 'some string value from LibTwo'
    }
}

// šŸ˜ž BAD: the newProperty from libTwo will  
// override the newProperty from libOne
libOne(user)
libTwo(user)
console.log(user) // {age: 29, newProperty: ʒ ()}

This is a very simple example where the mistake it's easy to spot, but imagine the multitude of libraries we are using these days. Just open up your nodeModules folder. It's almost impossible to be sure that no other lib will override your newProperty.

One way to improve this name collision is to generate some random names for the new property:

// šŸ˜ SLIGHTLY BETTER: the properties from LibOne  
// and LibTwo will not collide with each other, 
// but their names will be random
const uniquePropName = () => Math.random().toString(36).substring(7)

const user = {
    age: 29
}

const libOne = (obj) => {
    obj[uniquePropName()] = 'Property from LibOne'
}

const libTwo = (obj) => {
    obj[uniquePropName()] = function() {
        return 'some string value from LibTwo'
    }
}

libOne(user)
libTwo(user)
console.log(user) // {age: 29, auhy9: ʒ (): jzbsb: "Property from LibOne"}

While this will keep both properties, the new property name is not explanatory, and will also be different each time.

The answer there is to use Javascript symbols.

Symbols are a data type that has just one purpose. They are meant to be used as an identifier for object properties.

We can create a symbol by using the Symbol() function. Each time this function will return a unique value.

Keep in mind that you will not be able to see the actual symbol value. It does not return something like a unique identifier, or an object.

We can add descriptions to symbols, and even if the descriptions are equal, the actual symbols are not.

const sym1 = Symbol('my description here')
const sym2 = Symbol('my description here')
console.log(sym1 === sym2) // false

Therefore, we can use Javascript symbols in libraries to add the newProperty without being afraid of name collision:

// šŸ˜ƒ GOOD: using Symbols the properties from LibOne  
// and LibTwo will not colide, and we can
// the use the same description from both of them

const user = {
    age: 29
}

const libOne = (obj) => {
    obj[Symbol('newProperty')] = 'Property from LibOne'
}

const libTwo = (obj) => {
    obj[Symbol('newProperty')] = function() {
        return 'some string value from LibTwo'
    }
}

libOne(user)
libTwo(user)
console.log(user)
// { age : 29
// Symbol(newProperty) :  "Property from LibOne"
// Symbol(newProperty) :  ʒ () }

And that, my fellow coders, is how we tackle property collisions in JavaScript ā€“ by introducing symbols, the secret agents of property identification! You can checkout on my gitub the full code of this example.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.


Leave a Reply

Your email address will not be published. Required fields are marked *