Unable to fetch object value - javascript

I am struggling to figure out why I am getting "undefined" when trying to fetch a certain object value.
My object, called "message" looks like this:
{"username":"123","password":"123"}
When I try to fetch either username or password with the following:
message.username
message['username']
I get "undefined".
What's the correct way to fetch the values?
Code that gets the message and displays it:
window.messageBus.onMessage = function(event) {
displayText(event.data); // spits out {"username":"123","password":"123"}
}
function displayText(message) {
document.getElementById("message").innerHTML = message.username + ' - ' + message.password;
};
EDIT - The object is being received by Chromecasts "window.messageBus.onMessage" function. I assumed because I sent the message as a proper object, it should have bene spat back as a proper object, but it seems that might not be the case!

Well, no idea why it wasn't working with the code I posted, as by all means it should have.
Anyway, I fixed it by using "JSON.parse()" on the "message" variable passed to "displayText()"
I was then able to use "message.username" to get the value.

No point defining your variables in "", see the following example:
var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
alert(person.firstName);
That is the right way of defining and accessing the objects in Javascript

Related

Saving and getting an array in Localstorage?

I am trying to save an array into localstorage and then get it.
localStorage.setItem("savedquestionslist", questions);
console.log(localStorage.getItem(savedquestionslist));
The variable 'questions' is an array.
However I get this error:
ReferenceError: savedquestionslist is not defined.
I still get the error even if I do this:
localStorage.setItem("savedquestionslist", "test");
console.log(localStorage.getItem(savedquestionslist));
Does anyone know what the issue is? Thanks
savedquestionslist needs to be a string.
console.log(localStorage.getItem('savedquestionslist'));
The problem is in your syntax for getItem.
It takes in a string as an argument. You are passing a variable and the error represents that the variable savedquestionslist is not defined.
Change your code to :
localStorage.setItem("savedquestionslist", questions);
console.log(localStorage.getItem("savedquestionslist"));
An example would be
var questions = ['firstQuestion', 'secondQuestion', 'thirdQuestion'];
localStorage.setItem("savedquestionslist", questions);
console.log(localStorage.getItem("savedquestionslist"));
The error you're getting is because you forgot the quotes in the getItem call:
console.log(localStorage.getItem("savedquestionslist"));
// ------------------------------^------------------^
Or you can use literal access:
console.log(localStorage.savedquestionslist);
But in both cases, since local storage only stores strings, I'd use JSON, since otherwise your array won't be saved / retrieved correctly:
localStorage.setItem("savedquestionslist", JSON.stringify(questions));
console.log(JSON.parse(localStorage.getItem("savedquestionslist")) || []);
(The || [] is for if you've never set the item, it provides a default of an empty array.)

How to print out a label for each value in console.log()

I'm having trouble figuring out how to customize console.log() so that it automatically prints out the label for each argument I pass into it. For example, I often do something like this, so that it's clear what each log is printing out:
console.log('firstName: ', firstName);
I would love to be able to simplify this to:
my.log(firstName);
Is there any way to pass the variable names of the caller args into console.log()? Or is there another way to do this? My wish is that I don't have to type out the variable name twice, just the once. And ideally print out multiple arguments each with its own label on its own line in the console. I'm aware that I can access the arguments list, but I don't know how to un-eval() each argument to get just its variable name, if that makes sense. I'm hoping it's something super-easy I missed.
Doing it the way you want is impossible (the log function doesn't know what name you called things.)
The way I work around this is to use the object shorthand {firstName}to create a temporary object.
You can then either use .log or .table to display it:
const firstName = 'bob';
console.log({firstName});
console.table({firstName});
// It also works for multiple variables:
const lastName = 'smith';
console.log({firstName, lastName});
You could use console.table() to print things in a more readable form:
(Look in the real console to see it.)
var obj = {
firstName: "name",
lastName: "smith"
};
function log(obj) {
console.table(obj);
}
log(obj);
Try this :
var my = {
log : function(name) {
console.log('firstName: ', name);
}
};
my.log("Rohit");

Setting Variable Assignments with property display

I'm still a novice when it comes to JavaScript and was trying to make my code more cleaner and was wondering why the top scenario works but the bottom doesn't? Am I missing something?
var partner = document.getElementById('partner');
var providedBy = document.getElementById('providedBy');
partner.style.display = "none";
providedBy.style.display = "none";
But this does not?
var partner = document.getElementById('partner');
var providedBy = document.getElementById('providedBy');
collection = partner + providedBy;
collection.style.display = "none";
In the console it gives me error saying Cannot set Property 'display' of undefined. Am I supposed to define it somewhere first? I console logged the new variable and it returned both div elements.
collection is of type string as the + operator automatically call for both their toString() function.
Now what you are trying is to access a property of collection.style which does not exist because you are operating on a string. That's the reason for the error message you are getting.
You could do something like:
var collection = [];
collection.push(document.getElementById('partner'));
collection.push(document.getElementById('providedBy'));
collection.forEach(function(element) {
element.style.display = 'none';
}
which would be something I think you are trying to archive.
just to complement the accepted answer, I think you should understand why you get this error.
For what i understand from your code, you are trying to set the css of both variables partner and providedBy to display : none.
Your first piece of code works because you do this separately, while in your second code you try to add with the (+) operator both nodes, which evaluates to the string "[object HTMLDivElement][object HTMLInputElement]".
Then you try to call .style on that string which evaluates to undefined, and then you try to call display on that undefined value, this is where you get the error.
You could leave your code just like that since there are not too many variables, but if you wanted to do something that worked on multiple variables you could
create an array
push your objects into the array
create a function that loops over the elements of the array and set their style.display = "none" to individually.
In JavaScript you have to declare all of your variables. Secondly, you can't point to two objects at once by using the + operator. JavaScript interprets this as trying to concatenate the two objects, which it can't do in this way. It will return the string [object Object][object Object]
In order to affect two Objects at the same time you would need to create a function or use an existing method.

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]

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