Get a variable from Object Symbol - javascript

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).

Related

Custom string instead of "Object" in console.log

For convenience while debugging, I think it would be nice to print some custom string, rather than the default Object that appears when logging an object to the console.
In the following example, see how an object called example is marked by Object when it is logged to the console, whereas window is marked by Window when it is logged to the console. I guessed that the __proto__["Symbol(Symbol.toStringTag)"] property might be the way to go, since window's is set to Window. That didn't work, but maybe I'm just using it wrong.
That's because you're using the Symbol wrong -- you were on the right track. Symbol.toStringTag is a special well-known Symbol used by Object#toString to give you the console output, specifically the tag you're after. You can't wrap it in a string as you've done, or else you'll be literally setting the "Symbol.toStringTag" property, not the actual Symbol:
const example = {
key: "value"
};
example.__proto__["Symbol.toStringTag"] = "Example";
console.log(example); //You set the literal "Symbol.toStringTag" property -- wrong
Instead, don't wrap it in quotes and actually set the Symbol:
const example = {
key: "value"
};
example.__proto__[Symbol.toStringTag] = "Example";
console.log(example);
Which produces (on Chrome):

Get the description of a ES6 Symbol

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.

Equivalent of Python's KeyError exception in JavaScript?

I am trying to access a certain member in a JavaScript object. In order to do this, I need to try out a couple of key values.
For example, Object['text/html'] which will give me an export link for a HTML document. However, not every object of this type will have a text/html key pair value.
In Python I would solve this problem using a Try-Catch block, with the KeyError exception. If I can do something similar in javascript, as in use an exception in a Try-Catch block, that would be great.
However, if alternatives exists instead of try catch blocks, that do achieve the same end goal, I would like to know about them as well.
EDIT:
I would prefer to use an exception over using functions. I do this because the text/html key might not be there, but it should be there. An exception seems more appropriate for this scenario
Javascript doesn't generate an exception when reading or writing a property that doesn't exist. When reading it, it just returns undefined. When writing it, it just creates the property.
You could create your own function that tests to see if the property exists and throws an exception if it does not (but you'd have to call that function whenever), but JS doesn't make an exception out of that on it's own like you are asking for.
If you want to test if a key exists on an object in javascript, you can use this construct with the in operator:
var obj = {};
var key = "test";
if (key in obj) {
// key exists
} else {
// key doesn't exist
}
If you try to read a key that doesn't exist, you will get undefined as the value.
var obj = {};
var value = obj.test;
alert(value === undefined);
The in operator does a better job of telling you whether the key exists that testing for undefined because undefined is a legal value for a key that exists.
In many cases, where you control the values that the keys have and a key that is present will never have a falsey value, you can also just check if the key has a truthy value:
var obj = {};
var obj.test = "hello";
if (obj.test) {
// key exists and has a truthy value
}
If you want to make sure that the object itself has the property and not any prototype that it is inheriting from, then you can do this:
var obj = {};
var obj.test = "hello";
if (obj.hasOwnProperty(test)) {
// key exists on the object itself (not only on the prototype)
}
Read this!
The accepted answer is correct however omits some points.
1) Accessing nested object
Like someone pointed out in the comment, Javascript returns undefined when the key doesn't exists in the object.
However, if you need to access an object inside an object (or an Array, or a function), well this break.
let a = {};
let userName = 'js'
let data = a.response[userName];
Cuz you will received actually a TypeError, basically because we are trying to read a property of undefined, which doesn't have any.
VM187:2 Uncaught TypeError: Cannot read properties of undefined (reading 'js')
at <anonymous>:2:22
2 Answering the question
The Python principle "Ask forgiveness not permission" - explain is actually for the most part working well in Javascript (and PHP, you didn't ask but well..). There are for sure some difference, or some situation where the difference is important, but for most use cases is the same
So this is how you would do it:
try {
let data = a.key1.key2['whatever'].nested.damn.object;
console.log(data)
} catch (error) {
let data = "noope";
console.log(data);
}
As you can see, in Javascript you don't really care about the error type, (for the most part, sure other situation you should case). Is almost like anything is in a Python's
try:
a = "hello" + 1 + {} + [] # crazy stuff here
except BaseException as bleh:
print(str(bleh))
Documentatin
MDN Working with objects
How do I check if an object has a key in JavaScript? [duplicate]

trying to work dynamically with object properties in javascript

I'm trying to sort out if this is plausible but have gotten syntax errors at best. So I am wondering if it is at all possible.
What I have is an object (example only)
var myObj = {
something1_max:50,
something1_enabled:false,
something1_locked:true,
something2_max:100,
something2_enabled:false,
something2_locked:true,
something3_max:10,
something3_enabled:true,
something3_locked:true
}
and what I want to do through a function is do something like again for example to sum things up..
function displayDetails(theScope, obj)
{
console.log(obj.[theScope]_max);
}
(function(){displayDetails('something3', myObj);})()
so when displayDetails() is called whatever the scope I can see in this example the max for that scope. In the console log for the example I would hope to see 10
Properties of JavaScript objects can always be accessed as a string using the bracket syntax, ie object['property']. This, of course, means you can build that string dynamically:
console.log(obj[theScope + '_max']);
Put the property name string in brackets.
console.log(obj[theScope + '_max']);

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