Get the description of a ES6 Symbol - javascript

I wonder if there is a nice way to get the descriptions of a Symbol.
For example,
var s = Symbol(5);
The default implementation of the toString will simply print
Symbol(5)
I would like to find a way to extract the actual description i.e. 5

Symbol.description returns description of the symbol.
Simply do s.description in your case.

There is no neat way to do this. However, if you have registered a symbol in the global registry, you can use Symbol.keyFor():
var s = Symbol.for(5);
console.log(Symbol.keyFor(s));

String(symbol).slice(7, -1) || null
This works because String(symbol) explicitly coerce the symbol into a string e.g. Symbol('test') gets coerced into "Symbol(test)".
Doing a splicing on the from 7 to -1 does a splicing between the two brackets, thus capturing the description test
Note: that this may not work for object descriptions (e.g. Symbol({test})) as objects gets coerced into "[object Object]"

symbol-description package on npm
Returns description of provided symbol:
const symDesc = require('symbol-description')
symDesc(Symbol('foo')) // foo
It was published by me just now after reading this answer here.

Related

What does [].$ mean in JavaScript?

There is a function in JavaScript which calculates the sum of some digits, however I don't understand what this part ([].$) means:
const sum = d => d != [].$ ? `${d = [...`${d}`].join` + `} = ${eval(d)}` : ``
[].$
[].$ - what is it?
[].$ - what is it?
It's an empty array literal ([]) followed by a property accessor expression (.$) looking up the property called $.
Since arrays don't normally have a property with that name, presumably it's been set there (or potentially set there, given the check) by some previous code. If no code sets it, then it's a short way to write undefined (since [].$ is undefined when $ isn't a property of arrays).
For this particular code, it doesn't have any significant meaning. It's there just to represent the value undefined with the least amount of characters. It could equally be []._ or just undefined.
For how it's interpreted. #T.J.Crowder answer summarised it pretty well

Get a variable from Object Symbol

I have an object that when inspected by Developer Tools Console looks like this:
console.log("clicked: ", clickedMarker);
How can I get the address content form Symbol(vars)?
console.log("vars: ", clickedMarker["Symbol(vars)"]);
console.log("address: ", clickedMarker.address);
console.log("address2: ", clickedMarker["address"]);
console.log("vars2: ", clickedMarker["vars"]);
console.log("vars3: ", clickedMarker.vars);
console.log("Symbol(vars): ", clickedMarker._objectInstance["Symbol(vars)"]);
but it all comes out undefined.
Edit: This is a Typescript application but the Javascript solution worked fine.
The issue is likely that you are looking for a string key instead of a symbol one.
To read more about what a Symbol is (which is a primitive in javascript, anyway), please check this: https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Symbol
To solve the issue, find the correct Symbol by using the comfortable toString prototype, and make use of the getOwnPropertySymbols method of the generic Object:
// look for the symbol having key "vars" in the object's symbols list.
var mFound = Object.getOwnPropertySymbols(clickedMarker._objectInstance)
.find(e => e.toString() === "Symbol(vars)");
// Use the above symbol as the object's key.
var address = clickedMarker._objectInstance[mFound].address;
Please remember that, for further safety, you should check if mFound is effectively found (hence NOT undefined, or generically not falsey).

Why Symbols not convert string implicitly

Why Symbol('test').toString() works well, but I can't use '' + Symbol('test')?
It will throw Error:
cannot convert a Symbol value to a string
Why does the implicit type conversion not work? Why is the code not equal to '' + Symbol('test').toString()?
According to ECMA-262, using the addition operator on a value of type Symbol in combination with a string value first calls the internal ToPrimitive, which returns the symbol. It then calls the internal ToString which, for Symbols, will throw a TypeError exception.
So calling the internal ToString is not the same as calling Symbol.prototype.toString.
So I guess the answer to:
Why does the implicit type conversion not work?
is "because the spec says so".
You can, however you're not meant to do so by accident.
console.log(''+String(Symbol('My symbol!')))
// Symbol(My other symbol!)
console.log(Symbol('My symbol!').description)
// My other symbol!
console.log(Symbol.keyFor(Symbol.for('My other symbol!')))
// My other symbol!
Note: Symbol.keyFor only works for symbols created via the Symbol.for function.
Symbol.keyFor(Symbol('My symbol!')) will evaluate to undefined.
You can also use .description to get the string value used to create the symbol.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/keyFor
your type not string
'' + Symbol('test').toString()
you can check, Symbol is a new type in ES6
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol
The Symbol() function returns a value of type symbol, .....

JavaScript: Check if variable exist without classic if()

i've got the following situation.
In my script I have extracted all strings, that are publicated to the webpage, into an object like this.
var strings = {
one: "One",
two: "Two",
three: "Three",
}
Please don't ask why I want to do this, it's just a test case.
Now I want to push one of these strings, for example, into an alert(). this would look like this:
alert(strings.one);
So far so good, but I want to check if strings or strings.one exist and when it doesn't return an empty string.
What is a slick way to do this, without using the classic if(strings.one == undefined)?
EDIT
I've found a solution according to your answers and comments.
alert((window.strings) ? strings.one || "nope" : "nope");
This catches all cases i want to prevent:
I forgot to declare strings
strings.one doesn't exists
I hope this fits to "slick way"?!
You can use ||, which returns the first operand if it's truthy and the second otherwise:
alert(strings.one || "");
This will also catch other falsy values, but that probably won't be an issue for you.
You can use the ternary operator or u can do this if you want and empty string if string.one does not exist.
alert(string.one || '');

Javascript arrays and Meteor session

I have made an interesting observation. When trying to update an array that is stored in the Meteor session storage, the following code will not propagate the changes:
var tags = Session.get("Tags");
tags.push("a");
Session.set("Tags", tags);
But if I change the first line to use Session.get("Tags").slice(), everything depending on the session will update accordingly. I guess this is due to the fact that Meteor tests some references for equality and therefore does not update anything.
Is there a better way to manage lists stored in the meteor session store?
If I now try to remove an element from the collection (using array.remove() from here), the behavior turns out to be a bit ... of ... I am doing this inside a Meteor template event, the code looks like this:
"click .taglist li" : function(e) {
var tags = Session.get("Tags").slice();
var index = cardTags.indexOf(this);
Meteor._debug(Session.get("Tags").slice().indexOf("a"));
Meteor._debug("Removing tag \"" + this + "\", index: " + index, ", typeof(this) = " + typeof(this).toString());
tags.remove(index);
Session.set("Tags", tags);
}
This outputs:
1
Removing tag "a", index: -1, typeof(this) = string
So somehow, the cardTags.indexOf(this); statement seems to return -1 for almost any case. I guess I am doing something fundamentally wrong, as I am quite now to javascript, but somehow I can not figure out whats going on here.
Why will those two calls to indexOf() behave different?
I believe this is the same as this situation in Backbone.js. In order for the change event to be triggered, Meteor needs to have a new reference for the array, not just an updated copy of the old one.
In brief, in order to have the 'correct' behaviour, you'll need to clone the array, make the changes you want, and then do Session.set('foo', myCopiedArray).
In short: Use var index = cardTags.indexOf(this.toString()); instead.
Long version:
When using strings in JavaScript, those are strings, whereas typeof 'test' returns string.
Let's take a look at the following code in order to get find out another way to represent strings in JavaScript:
var func = function () {
return this;
};
console.log(func.call('test'));
The console (at least FireBug) won't show us "test", but instead it shows String {0="t", 1="e", 2="s", 3="t" }. typeof would return "object".
The content of the this statement seems to need to be an object. In order to convert a string into a "String" object we can do console.log(new String('test'));, which is the same as the previously logged value.
To convert a string object into a string (data type), just use its prototype toString.

Categories