Symbols are one of the new features of ES6. Originally they were intended to help create private components of the object, but the concept was abandoned and today they are mainly used as non-text object property names, which, in combination with their other features, allows us to create a values which guaranteed to be unique.
Create a Symbol
As Symbol is primitive value, the way it is created can be a bit confusing:
//create a Symbol and empty object
let myFirstSymbol = Symbol();
let obj = {};
//add a new property
obj[myFirstSymbol] = "Hello World!";
console.log(obj[myFirstName]); //"Hello World!"
Symbol, unlike other primitive values, has no literal form like:
let string = "Hi!"
let number = 42
let bool = false
Which may be a certain difficulty in working with it. Fortunately, the description of the symbol and the (explicit or implicit) method called toString()
come in handy.
let mySecondSymbol = Symbol("Hey, I'm second!");
//console.log calls `toString()` method implicitly
console.log(mySecondSymbol); //"Symbol("Hey, I'm second!")"
It is worth noting that the symbol description itself is completely optional, it cannot be used to access the Symbol, and it does not affect the Symbol itself in any other way. Its only purpose is to help us work with the code.
Share a Symbol
Speaking of working with code, what if I want to use the same Symbol in many different parts of my application? Maybe I should create my own separate file for such global Symbols? An interesting option, but completely unnecessary. The ES6 specification offers us the possibility of storing Symbols in the Global Symbol Register(GSR), which, due to being global, is open to the public.
To create / get / work with shared symbols, you only need to know two methods: Symbol.for()
, Symbol.keyFor()
Symbol.for()
first searches the GSR to see if there is a Symbol with the given key ("userID"). If so, this method will return an existing Symbol, if not, the Symbol will be created and registered in GRS, and then returned.
let userId = Symbol.for('userId');
let obj = {};
obj[userId] = 'qwerty123';
let userId_2 = Symbol.for('userId');
console.log(obj[userId_2]) //qwerty123
console.log(userId === userId_2) //true
The Symbol.keyFor()
method is used to retrieve a Symbol key that already exists in the GRS. If we use it for a Symbol that is not shared, this method will return undefined
let symbol_1 = Symbol.for('the best Symbol');
console.log(Symbol.keyFor(symbol_1)) //'the best Symbol'
let symbol_2 = Symbol.for('the best Symbol');
console.log(Symbol.keyFor(symbol_2)) //'the best Symbol'
let symbol_3 = Symbol('the best Symbol');
console.log(Symbol.keyFor(symbol_3)) // undefined
Where is my property?
In order to maintain functionality with ES5, some methods may not "see" Symbols. It is worth remembering about it when we start using them:
let symbolProp = Symbol("prop1");
let obj = {
[symbolProp] : "I AM SYMBOL",
"prop2": "Strings are cool",
"prop3" : false,
"prop4" : 69
}
//no Symbol π
Object.keys(obj) //Β ["prop2", "prop3", "prop4"]
//still no Symbol π
Object.getOwnPropertyNames(obj) //["prop2", "prop3", "prop4"]
//..again ππ
JSON.stringify(obj) // "{\"prop2\":\"Strings are cool\",\"prop3\":false,\"prop4\":69}"
//πππ
for(prop in obj) {
console.log(obj[prop])
}
// Strings are cool
// false
// 69
In the ES6 specification, the Object.getOwnPropertySymbols()
method was added to return an array of all symbol properties found directly upon a given object.
//πππ
Object.getOwnPropertySymbols(obj)
// [Symbol(prop1)]
Working with symbols can be tricky, but if you need unique values in your code, they're very helpful. I hope I was able to encourage you to use them.
Thanks for reading π
Top comments (0)