One pattern that keeps coming up when I’m spelunking older NPM packages for Node.js is using Symbols to define properties on an object.
A Symbol is a way to create an object that’s a unique identifier in a javascript program. There’s a global function named Symbol
you can use to create you symbol objects
const symbol1 = Symbol('foo')
const symbol2 = Symbol('baz')
const symbol3 = Symbol('bar')
The syntax is a little weird — usually a title case identifier like Symbol
would indicate a constructor-function/class — but trying to use Symbol
as a constructor-function/class results in an error
> foo = new Symbol('123')
Uncaught TypeError: Symbol is not a constructor
at new Symbol (<anonymous>)
The intent behind these symbols seems to be a system for creating unique object properties.
const hello = Symbol('hello')
const foo = {}
foo[hello] = function() {
console.log('Hello World')
}
// call your method
foo[hello]()
The advantage of a symbol is you end up creating a property that
- other programmers can’t replace unless you give them access to the same symbol variable
-
won’t show up if you use
Object.keys(foo)
or loop over the object withfor ... in
orfor ... of
loops
It’s a weird idea, but when you’re catching up on a decade of language innovation I find it’s best to accept and move on.
Another thing that made Symbols difficult to understand were the less common javascript syntaxas that come along with them. For example, if you want to use a symbol in object literal notation, you do something like this
const hello = Symbol('hello')
const foo = {
[hello]: function() {
console.log('Hello World')
}
}
// call your method
foo[hello]()
Normally [hello]
would indicate an array with a single item (your symbol) — but not when you write this inside an object literal declaration. Instead, this is called a computed property. It’s not just for symbols either — you can compute anything you like to get a property with a particular name/key.
const a = 'hel'
const b = 'lo'
const foo = {
[a+b]: function() {
console.log('Hello World')
}
}
// call your method
foo.hello()
You can also use this computed property syntax to define methods in a class
const hello = Symbol('hello')
class HelloWorld {
[hello]() {
console.log('Hello World')
}
}
const foo = new HelloWorld;
foo[hello]()
I see less of this in more recent javascript code bases — but if you’re debugging an application chances are you’ll run across it. Yesterday’s fads are today’s headaches.