I have this code:
var string = {
nameString : "nameValue",
nameString2 : "nameValue2",
nameString3 : "nameValue3",
datathing : 0,
};
var data = {
data : 1,
dataNum2 : 2,
dataNum3 : 3,
dataNum4 : 4,
};
var thing = {
datathing1 : 10,
datathing2 : 20,
datathing3 : 30,
datathing4 : 40,
};
var object = {
object1 : string,
data1 : data,
thing1 : thing,
};
Why do neither of these means to access the data work:
alert("testReference= " + object['object1']['string']['nameString']);
alert("testReference= " + object.object1.string.nameString);
I cannot understand it, even though similar examples found below and textbooks state explicitly that they should work:
Accessing nested JavaScript objects with string key
Thanks in advance for any input!
I am currently constructing an object and passing it around, a 'for in' will bring up the values but a 'typeof' test or any other way I try and access will not work, either I will encounter an error (which breaks the program, I think) or I get 'undefined'....
One last thing if this gets solved, is it ok to nest a key that is the same name value as its parent, such as data.data - this leads to the possibility of further nesting such as data.data.data...
Let's look at what's wrong with each example, then take a look at the way that works right.
Example 1
object['object1']['string']['nameString']
We expect object['object1'] to return the object string, right? So lets simplify the big expression by replacing that part of it. That'll make it easier for us to understand.
So now we have string['string']['nameString'].
But string has no member called 'string', so string['string'] returns undefined.
And when you try to treat undefined as an object, you get an error!
Example 2
object.object1.string.nameString
We expect object.object1 returns the object string, right? So lets simplify the big expression by replacing that part of it. That'll make it easier for us to understand.
So now we have string.string.nameString.
But string has no member called 'string', so string.string returns undefined.
And when you try to treat undefined as an object, you get an error!.
What You Want
object.object1.nameString (or object['object1']['nameString'])
We expect object.object1 returns the object string, right? So lets simplify the big expression by replacing that part of it. That'll make it easier for us to understand.
So now we have string.nameString, and we expect that to return "nameValue".
And it does!
Related
I might be wrong , but curious to know whether can i construct an object with key value pair, with value accepting space only
Somehow after parsing i need to get as
properties:
name:
value: //accepting space
let property = { name: {'value':} }; //currently its giving me error like expression expected
I need to give something like this , is it possible in js or in react
Any help will be highly appreciated
You can create objects with undefined or null values, like this:
let property = {
name: undefined,
value: undefined
}
let null_property = {
name: null,
value: null
}
which is the closest you can get to 'empty space' in Javascript, if you mean what I think you mean.
You can't, however, not assign anything at all in your syntax because Javascript requires that something be assigned to every single variable. You can test this by noting that:
let thing;
and
let thing = undefined;
are the EXACT same line of code from your computer's perspective. The first is simply a convenient shorthand way to write the second.
// My input String
// Could be on : true, on : false, bri : 255, etc, etc
var inputString = 'on : true'
console.log(inputString);
var wrongResult = { inputString }
console.log(wrongResult);
// The result that I am trying to achieve
var desiredResult = {
on : true
}
console.log(desiredResult);
Run it: https://repl.it/LCDt/4
I created the above code snippet to demonstrate the problem that I am experiencing. I have an input string that I receive that could be "on : true", "on : false", "bri : 250", "sat : 13", etc. When posting this data to a server, the format that works is seen above as the "desireResult".
But, when taking a string, such as 'on : true', in a variable, and placing it inside {}, it always seems to create a dictionary with the variable name as the key and the string itself as the value.
Can someone explain why this is and how to get around it?
Can someone explain why this is
Because the syntax { foo } means "Create an object, give it a property called foo, give that property the value of the foo variable.
how to get around it
Parse the data. Assign it explicitly.
Start by splitting the string on :. Then remove the white space. Then test is the second value is a number or a keyword. And so on.
This would be easier if the data you were receiving was in a standard format. Then you could use an existing parser. If you have control over the input: Change it to be valid JSON and then use JSON.parse.
You could use JSON.parse for that but you need to feed him valid JSON.
You need to have an string in form of:
{"on":true}
using JSON.parse('{"on":true}') will return you the desired object.
I want to pass following payload to the API
params[field1]: value1
params[field2]: value1
....
params[fieldN]: valueN
I have field and value coming from an object.
var params = {};
jQuery.each($scope.linkParams, function(a, b) {
params.params[a] = b; // returns undefined variable error
// I also tried other options but all result in one or another error
// Some doesn't result into an erro but doesn't get merged. See below merge requirement
});
I also wants to merge the above created object to another object with
jQuery.extend(extraParams, params);
How to achieve the rquired object?
Update
$scope.linkParams = {
field1: 'value1',
field2: 'value2',
....
};
You have two questions, so I'll address them one at a time.
(For a TL;DR, I emboldened the solution text. Hopefully the rest is worth the read, though.)
Object Serialization is Pretty Magical, but Not Quite That Magical
If I had a JS object that I instantiated like the following:
var cat = {
'meow': 'loud',
'type': 'Persian',
'sex': 'male'
}
then it is certainly true that you get attribute reference for free. That is, you can say something like cat.meow, and your runtime environment will make sense of that. However, JS will not automatically create properties of an object that you have referenced do not exist, unless you are referencing them to create them.
cat.health = 'meek' will work, but cat.ears[0] = 'pointy' will not.
var cat = {
'meow': 'loud',
'type': 'Persian',
'sex': 'male'
}
cat.health = 'meek'
alert(cat.health)
cat.ears[0] = 'pointy'
alert(cat.ears[0])
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You'll notice that the first alert happens and contains the expected value, but the second alert never comes. This is because the code fails on the line with cat.ears[0] = 'pointy', and it stops execution at that point.
This may seem to contradict what I just said, but look closely at what's happening. When we attempt to initialize the first element of cat.ears, we must reference the cat.ears property, which does not exist.
JS implementations won't assume that you want to create items up the chain eternally, which is likely by design -- if it didn't throw errors and instead just created any properties or objects that needed to exist in order for your program to by syntactically sound, many pieces of software would silently break when they failed to include required libraries. If you forgot to include JQuery, it'd just create a $, a JQuery variable, and all of the properties of those objects you reference in your code. It'd be a proper mess to debug.
In short, that's what you're -- probably accidentally -- assuming will work here. params.params is analogous to cat.ears in the above example. You may have some reason for doing this, but assuming you don't, your code should function if you simply change params.params[a] to params[a].
JQuery.extend()
Assuming that extraParams is a valid array/object, the code you have written will work once params doesn't break your code anymore, however: do note that this will modify your extraParams object. If you want a new object to contain both params and extraParams, write something more like:
var args = $.extend({}, params, extraParams)
That will modify an empty object and add in the contents of params and extraParams. See the JQuery documentation for more information.
Some manipulations and I was able to achieve the required results.
I am posting the code for further reference:
var d = {};
jQuery.each($scope.linkParams, function(a,b) {
a = "params[" + a + "]";
d[a] = b;
});
jQuery.extend(extraParams, d);
This is a fairly common question here in SO, and I've looked into quite a few of them before deciding to ask this question.
I have a function, hereby called CheckObjectConsistency which receives a single parameter, an object of the following syntax:
objEntry:
{
objCheck: anotherObject,
properties: [
{
//PropertyValue: (integer,string,double,whatever), //this won't work.
PropertyName: string,
ifDefined: function,
ifUndefined: function
}
,...
]
}
What this function does is... considering the given parameter is correctly designed, it gets the objCheck contained within it (var chk = objEntry.objCheck;), It then procedes to check if it contains the properties contained in this collection.
Like this
for(x=0;x<=properties.length;x++){
if(objCheck.hasOwnProperty(properties[x].PropertyName)){
properties[x].ifDefined();
}
else{
properties[x].ifUndefined();
}
What I want is... I want to bring it to yet another level of dynamicity: Given the propositions that IfDefined and IfUndefined are functions to be called, respectively, if the currently-pointed PropertyName exists, and otherwise, I want to call these functions while providing them, as parameters, the very objCheck.PropertyName's value, so that it can be treated before returning to the user.
I'll give a usage example:
I will feed this function an object I received from an external provider (say, a foreign JSON-returning-WebService) from which I know a few properties that may or may not be defined.
For example, this object can be either:
var userData1 = {
userID : 1
userName: "JoffreyBaratheon",
cargo: "King",
age: 12,
motherID : 2,
//fatherID: 5,--Not defined
Status: Alive
}
or
var userData2 = {
userID :
userName: "Gendry",
cargo: "Forger Apprentice",
//age: 35, -- Not Defined
//motherID: 4,-- Not Defined
fatherID: 3,
Status: Alive
}
My function will receive:
var objEntry=
{
objCheck: userData1,
properties: [
{
PropertyName: "age",
ifDefined: function(val){alert("He/she has an age defined, it's "+val+" !");},
ifUndefined: function(){alert("He/she does not have an age defined, so we're assuming 20.");},
},
{
PropertyName: "fatherID",
ifDefined: function(val){alert("He/she has a known father, his ID is "+val+" !");},
ifUndefined: function(){alert("Oh, phooey, we don't (blink!blink!) know who his father is!");},
}
]
}
CheckObjectConsistency(objEntry); // Will alert twice, saying that Joffrey's age is 12, and that his father is supposedly unknown.
ifDefined will only actually work if, instead of properties[x].ifDefined();, I somehow provide it with properties[x].ifDefined(PropertyValue);. And here, at last, lies my question.
Being inside the consistency-checking-function, I only know a given property's name if it's provided. Being inside it, I can't simply call it's value, since there is no such function as properties[x].ifUndefined(properties[x].GetValueFromProperty(properties[x].PropertyName)) ,... is there?
I'm sorry. Not being a native english speaker (I'm brazilian), I can't properly express my doubts in a short way, so I prefer to take my time writing a long text, in an (hopefully not wasted) attempt to make it clearer.
If, even so, my doubt is unclear, please let me know.
I think you're looking for the bracket notation here. It allows you to provide an arbitrary value as key to access the object. Also, you know its name. You have your properties object right?
objEntry.properties.forEach(function(property){
// Check if objCheck has a property with name given by PropertyName
if(!objEntry.objCheck.hasOwnProperty(property.PropertyName)){
// If it doesn't, call isUndefined
property.isUndefined();
} else {
// If it does, call isDefined and passing it the value
// Note the bracket notation, allowing us to provide an arbitrary key
// provided by a variable value to access objCheck which in this case is
// the value of PropertyName
property.isDefined(objEntry.objCheck[property.PropertyName]);
}
});
Oh yeah, forEach is a method of arrays which allows you to loop over them. You can still do the same with regular loops though.
I have an object (returned from jQuery ajax) that looks like this:
data:{
materials:{
1:{
id:1,
name:"jacob"
}//1 (some integer)
}//materials
}//data
I'm trying to access name, but I can't get passed the object 1. I tried using makeArray() like this
var m = $.makeArray(data.materials);
var m0 = m.shift();
console.log(m);
console.log(m0);
$isArray(m) & $.isArray(m0) return true, but m and m0 both return:
1:{
id:1,
name:"jacob"
}//1 (some integer)
I expect that shift() to return the object that's inside of 1.
When I try to access m0.name it returns undefined, and when I try to access m[1] it returns undefined.
btw data.materials["1"].name works. the problem is 1 is variable (I don't know what it will be, so I wanted to use shift() which doesn't work on an object).
EDIT: So it seems that there is a limitation within makeArray(): since an object property is not supposed to be named with a number, that function does not convert the rest of the object and the output is some kind of object-array hybrid (on which you cannot use array functions like shift()), so the quick-n-dirty solution I came to was to loop thru it like this:
var m = data.materials,
id;
for ( key in m ) { id = key; }
console.log( m[id].name );
It's not all that clean, so if there's a better way, please let me know.
p.s. The 1:{} is there in the first place because the controller returns multiple "materials" under certain conditions (which will never be true when this js is used).
You should use data.materials["1"].name
http://jsfiddle.net/nq4RE/
Jacob, I see you updated your question.
To use a variable, you simply call data.materials[your_variable_here].name
http://jsfiddle.net/nq4RE/1/
Did you try: data.materials[1].name?
But in my opinion using number as property name is misleading.