Reputation: 37905
I am learning the Symbol feature of ES6.
So in node, I write the following (in Typescript actually). It compiles fine, but the console logs "Not found" What am I doing wrong? It seems to me that it ought to work.
This example comes from this article
"use strict"
var levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
function log(level: Symbol, message)
{
switch(level)
{
case Symbol.for('debug'):
console.log(`Debug Message: ${message}`);
break;
case Symbol.for('info'):
console.log(`Info Message: ${message}`);
break;
case Symbol.for('warn'):
console.log(`Warn Message: ${message}`);
break;
default:
console.log("Not found");
}
}
log(levels.DEBUG, 'debug message');
log(levels.INFO, 'info message');
Update
As pointed out in the accepted answer, this will work:
var levels = {
DEBUG: Symbol.for('debug'),
INFO: Symbol.for('info'),
WARN: Symbol.for('warn')
};
function log(level: Symbol, message)
{
switch(level)
{
case Symbol.for('debug'):
console.log(`Debug Message: ${message}`);
break;
case Symbol.for('info'):
console.log(`Info Message: ${message}`);
break;
case Symbol.for('warn'):
console.log(`Warn Message: ${message}`);
break;
default:
console.log("Not found");
}
}
log(levels.DEBUG, 'debug message');
log(levels.INFO, 'info message');
Second Update
Also, as pointed out by @Felix Kling, this is even better:
var levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn')
};
function log(level: Symbol, message)
{
switch(level)
{
case levels.DEBUG:
console.log(`Debug Message: ${message}`);
break;
case levels.INFO:
console.log(`Info Message: ${message}`);
break;
case levels.WARN:
console.log(`Warn Message: ${message}`);
break;
default:
console.log("Not found");
}
}
Upvotes: 1
Views: 64
Reputation: 631
Every call to Symbol creates a new instance of a Symbol.
So Symbol('foo') === Symbol('foo') is false.
The Symbol.for method searches for a given key. If the key is not found it will be created. Otherwise it returns the already defined value.
"use strict"
var levels = {
DEBUG: Symbol.for('debug'),
INFO: Symbol.for('info'),
WARN: Symbol.for('warn'),
};
function log(level, message)
{
switch(level)
{
case Symbol.for('debug'):
console.log(`Debug Message: ${message}`);
break;
case Symbol.for('info'):
console.log(`Info Message: ${message}`);
break;
case Symbol.for('warn'):
console.log(`Warn Message: ${message}`);
break;
default:
console.log("Not found");
}
}
log(levels.DEBUG, 'debug message');
log(levels.INFO, 'info message');
Upvotes: 3
Reputation: 40842
The reason is because Symbol('debug') !== Symbol.for('debug')
.
You need to write:
var levels = {
DEBUG: Symbol.for('debug'),
INFO: Symbol.for('info'),
WARN: Symbol.for('warn'),
};
The above syntax using the
Symbol()
function will not create a global symbol that is available in your whole codebase. To create symbols available across files and even across realms (each of which has its own global scope), use the methodsSymbol.for()
andSymbol.keyFor()
to set and retrieve symbols from the global symbol registry.
Upvotes: 3
Reputation: 245419
Symbol('somestring');
Doesn't create a global Symbol.
Symbol.for('somestring');
Either gets a previously defined global symbol or creates a new global symbol.
Therefore, the first time you check your case
statements, you're creating new symbols rather than checking against your previously defined symbols.
If you use Symbol.for('somestring')
when defining the symbols in the first place, they'll be found when you check them later.
Upvotes: 4