javascript: access object (array) by array notation string - javascript

I would like to access the object provided only it's string path in form of array is known.
1.) there is an object, where
root["obj1"]["obj2"] = 1;
(in common case root["obj1"]...["objN"])
2.) I have ONLY string objectPath known:
var objectPath = 'root["obj1"]["obj2"]'
3.) I need NOT only READ the object, but SET it's value, like
objectPath = 2;
//so root["obj1"]["obj2"] === 2
As I understand
there might be some options with eval(), but it gets the value, not the variable;
one can loop through all objects of root, make convertion to "root.obj1.obj2" (which is not the case, as "obj1" can easily be "obj with spaces1") and check if given string equals to current object in the loop.
http://jsfiddle.net/ACsPn/
Related Link:
Access object child properties using a dot notation string

I wrote a function for you, trying to make it as pretty and reusable as possible :
function setProp(path, newValue, holder) {
var t = path.split(/[\[\]"]+/).filter(function(v){return v}),
l = t.pop(), s, o = holder || window;
while (s = t.shift()) o = o[s];
o[l] = newValue;
}
You use it like this :
setProp('root["obj1"]["obj2"]', 2);
If your root object isn't in a global variable, pass the relevant holder as third argument.
Demonstration (open the console to see the changed root object)

Related

What is function with brackets mean?

Does anyone know what is test[name] mean?
function test(value){
copy(value||{},this);
}
test[name] = function(){
return "test"
}
This will be easiest to explain with an example:
var name = "foo";
test[name] = function(){
return "test"
};
This would add a property named "foo" to the object test, and the value of that property is a function. It doesn't matter in this case that the object test is actually a function, you can assign properties to functions just like any other object in JavaScript.
You could call this function using any of the following methods:
test[name]()
test["foo"]()
test.foo()
Note that test[name]() will not work if the name variable is assigned to something different, for example name = 'bar'.
Javascript has two sets of notation for accessing objects, dot notation (obj.property) and bracket notation (object[property]). More on that at MDN.
test[name] = function (){} assigns an anonymous function to the name property on the the test object (which itself is a function). In this case (as noted by the comments) the variable name is being used to access the property.
This may seem a little strange at first, but it's helpful to remember that in javascript, functions are objects.
All functions in Javascript are also objects. This adds a property to the test function object with a value which is an anonymous function.
For example:
function test(){
return "foo";
}
// test is a function, so it is also an object and
// it can have properties assigned to it
test.x = function(){
return "bar";
};
test(); // "foo"
test.x(); // "bar"
Of course just like with any object you can also use bracket notation:
var name = 'hello';
test[name] = function(){
return "HELLO!";
};
test.hello(); // "HELLO!"
In JavaScript, functions are objects. They have properties. test[name] sets a property (named whatever the name variable holds) to a function.
when you have a javascript object with defined properties you can access the property either with the dot notation obj.property or with the square brackets notation obj[property]
the property could also be a function so if you have an object:
var test = {
foo : function(arg){ console.log(arg) },
bar : 'hello'
};
you can call test.foo('bar') also by doing test['foo']('bar')
This is especially useful in iterations or when you dont know a priori what the name of the property is going to be. For example:
var fun = 'foo';
test[fun]('hello world');
Naturally it's up to you to do proper checks such as
if ('function'==typeof test['foo']){ test['foo']('bar'); }
Also note that you can do checks on the fly like so:
test[ fun || 'foo']('hello');
Taken from the Mozilla page
One can think of an object as an associative array (a.k.a. map, dictionary, hash, lookup table). The keys in this array are the names of object members
There are two ways to access object members: dot notation and bracket notation (a.k.a. subscript operator).
So
test[name] = function (
means: there are (if everything is ok) two objects: test and name (and we know that at least test is present, because you defined it one line before: function test(value))
take the test object (if there isn't a test object an error will happen). Then access the key/value pair with the key calculated from the name object and there put a function.
Now, how the key is calculated from the name object? The same page from before tells us:
Property names must be strings. This means that non-string objects cannot be used as keys in the object. Any non-string object, including a number, is typecasted into a string via the toString method.
Note that the description is a little wrong... test[null] == test["null"] and test[undefined] == test["undefined"], so perhaps the truth is that under the covers something like String(key).valueOf() is done (the String function will convert null to "null" and undefined to "undefined")
Some examples (where => means "is equivalent to, with this values")
var name = 'foo';
test[name] => test['foo']
var name = 123;
test[name] => test['123']
var name = 123.3;
test[name] => test['123.3']
var name = new Date();
test[name] => test['Wed Aug 14 2013 17:35:35 GMT+0200 (...)']
var name = null;
test[name] => test['null']
var name = undefined;
test[name] => test['undefined']
var name = [];
test[name] => test['']
var name = [1,2,3];
test[name] => test['1,2,3']
var name = {};
test[name] => test['object Object']
and so on...
The brackets are how you reference a property via a key into the hash that javascript objects are.

LocalStorage, JavaScript and Objects

I need to store an object in localStorage - and I know that in order to do so, I have to convert the object into a string. All cool.
My problem is in actually creating the object in the first place: I have two values in sessionStorage that need to be added to the object which is then passed into localStorage. However, when I try to create the object, one value is being stored as the variable name rather than its (numeric) value. Any idea whats going on here?
var siteName = sessionStorage['1'];
var siteID = (+sessionStorage['2']);
var temp = {siteID:siteName};
alert(typeof siteID);
alert(JSON.stringify(temp));
The first alert confirms that siteID is indeed a number type, but the second alert shows that the variable name (siteID) is stored rather than its numeric value.
This line:
var temp = {siteID:siteName};
...creates an object containing a property called siteId with the value taken from the siteName variable.
If you want the property name to be taken from the siteID variable instead:
var temp = {};
temp[siteID] = siteName;
Or in ES2015 (aka "ES6") you could use the new computed property name syntax:
// ES2015+ only!
var temp = {[siteId]: siteName};
In JavaScript, you can access/create properties on objects in two different but equal ways: Using dotted notation with a literal property name:
obj.foo = "bar"; // Creates a `foo` property on `obj` with the value `"bar"`
...or using bracketed notation and a string:
obj["foo"] = "bar"; // Does the same thing
The keys in object initializers like your var temp = {siteID:siteName}; are always used literally (although they can optionally be in quotes); there's no way with an object initializer to have a key taken from a variable instead. So you have to do it as a two-step process, first create the object, then set the property.
So, if you do
temp[siteID] = siteName;
...the number in siteID will be converted to a string and will become the property name, with the value of siteName being the value.
var temp = {};
var key = 1;
temp[key] = "value";
console.log(temp[1]); // "value"
console.log(temp["1"]); // "value"
(Property names are always strings in JavaScript [for now].)
Change it to this.
var temp = {};
temp[siteName] = siteID;
Or if the typeof test was meant to show the property name, you'd reverse them.
var temp = {};
temp[siteID] = siteName;
But be aware that siteID is considered a String from that point forward.

How can I avoid using `eval()` in this example?

I'm trying to use a string as a reference to a variable to pass into a function. For example:
var names = ['Peter', 'John'],
var hasName = function(name){
var params = ['names'];
return $.inArray(name, eval( params[0] )) === -1;
};
How to avoid eval()?
EDIT:
The string from params[0] is comming from a data-qval of an input in my html. The array that contains the actual data can be declared anywhere, params[0] is just a reference to that array passed in as string in data-qval, it's a parameter. I pasted my plugin's code here .
http://pastebin.mozilla.org/1598528 Line 101.
Full example: http://jsfiddle.net/elclanrs/ZsS2D/29/
It currently works, I'm just looking for a way get rid of eval()...
In that particular case, just use names:
var names = ['Peter', 'John'],
var hasName = function(name){
var params = ['names'];
return $.inArray(name, names ) === -1;
};
(See also the note below.) (Your edit makes the above not applicable.)
If you're trying to look up the names array in some container using the string "names", you'd have to have a reference to the container, e.g.:
var obj = {
names: ['Peter', 'John'
};
var hasName = function(name){
var params = ['names'];
return $.inArray(name, obj[params[0]] ) === -1;
};
If there is no container other than the variable scope in which you're doing this, you'll have to use eval. But you can (and usually should) adjust things so you have a container (as above) so you can avoid it. Note that if names is declared at global scope, you do have a container (window).
So to summarize:
If names is a var at global scope (or an implicit global), window[params[0]] will give you a reference to it.
If names is already in some container object, you can use container[params[0]] to get a reference to it.
If names is a var within a function, you cannot get at it using a runtime string without eval; ideally, rather than var names = [...];, use var container = {names: [...]}; and then you can use container[params[0]].
Note that your function is called hasName, but it returns true when the array doesn't have the name and false when it does. You probably want !== -1, not === -1.
Isn't this enough?
var hasName = function(name){
return $.inArray(name, names) > -1;
};
Also, notice the comparison
Because JavaScript treats 0 as loosely equal to false (i.e. 0 ==
false, but 0 !== false), if we're checking for the presence of value
within array, we need to check if it's not equal to (or greater than)
-1.
Strings as references to variables? If it's a global object in a browser, it will be in the window object, so you can just do window[variableName] to get its value. Same for objects, i.e. instead of object.foo, you can do object['foo'] or bar = 'foo', object[bar]. For locally scoped variables, you cannot do it without using an object or eval.
if names is global, you can use the global namespace, i.e. window
var hasName = function(name,namespace){
namespace = namespace || window;
return $.inArray(name, namespace.names) > -1;
};
hasName('Peter'); //=> true;
This may also be an idea:
var MYNS = { names:['Peter','John']
,hasName: function(name){
return $.inArray(name, this.names) > -1;
}
};
MYNS.hasName('Peter'); //=>true

object Key in javascript class/dictionary?

I have a Javascipt object which I use as dictionary
var obj={
xxx:'1'
yyy:'2'
}
However -
xxx and yyy should be a jQuery object.
something like :
var obj =
{
$('#div1'):'1' ,
$('#div2'):'2'
}
is it possible ?
also, How can I get the "value" for key $('#div2') ?
p.s.
I the $.data cant help me here since its also a key value
and i need in the key - object Type also.
Object keys can only be strings ( or Symbol), period. See Member Operators - Property Names # MDN.
Choose a reasonable string representation, and use that. In this case, I'd say the selector string looks like a decent choice:
{
'#div1': '1',
'#div2': '2'
}
also, How can I get the "value" for key $('#div2') ?
Use one of the member operators, either dot notation
var obj = { /* stuff */ };
var value = obj.propertyName;
console.log(value);
or bracket notation (more useful for property names not known until runtime):
var value = obj['propertyName'];
Use a WeakMap which works like a dictionary where the key can be anything. Note that you cannot list all the keys of the map
const aMap = new WeakMap;
const anObject = {};
aMap.set(Number, "It's the Number class")
aMap.set(anObject, "It's an object")
console.log(aMap.get(Number)) // It's the Number class
console.log(aMap.get(anObject)) // It's an object

How can I store reference to a variable within an array?

I'm trying to create an array that maps strings to variables. It seems that the array stores the current value of the variable instead of storing a reference to the variable.
var name = "foo";
var array = [];
array["reference"] = name;
name = "bar";
// Still returns "foo" when I'd like it to return "bar."
array["reference"];
Is there a way to make the array refer to the variable?
Put an object into the array instead:
var name = {};
name.title = "foo";
var array = [];
array["reference"] = name;
name.title = "bar";
// now returns "bar"
array["reference"].title;
You can't.
JavaScript always pass by value. And everything is an object; var stores the pointer, hence it's pass by pointer's value.
If your name = "bar" is supposed to be inside a function, you'll need to pass in the whole array instead. The function will then need to change it using array["reference"] = "bar".
Btw, [] is an array literal. {} is an object literal.
That array["reference"] works because an Array is also an object, but array is meant to be accessed by 0-based index. You probably want to use {} instead.
And foo["bar"] is equivalent to foo.bar. The longer syntax is more useful if the key can be dynamic, e.g., foo[bar], not at all the same with foo.bar (or if you want to use a minimizer like Google's Closure Compiler).
Try pushing an object to the array instead and altering values within it.
var ar = [];
var obj = {value: 10};
ar[ar.length] = obj;
obj.value = 12;
alert(ar[0].value);
My solution to saving a reference is to pass a function instead:
If the variable you want to reference is called myTarget, then use:
myRef = function (newVal) {
if (newVal != undefined) myTarget = newVal;
return myTarget;
}
To read the value, use myRef();. To set the value, use myRef(<the value you want to set>);.
Helpfully, you can also assign this to an array element as well:
var myArray = [myRef];
Then use myArray[0]() to read and myArray[0](<new value>) to write.
Disclaimer: I've only tested this with a numerical target as that is my use case.
My solution to saving a reference is to pass a function instead:
If the variable you want to reference is called 'myTarget', then use:
myRef = function (newVal) {
if (newVal != undefined)
myTarget = newVal;
return myTarget;
}
To read the value, use myRef();. To set the value, use myRef(value_to_set);.
Helpfully, you can also assign this to an array element as well:
var myArray = [myRef];
Then use myArray0 to read and myArray[0](value_to_set) to write.
Disclaimer: I've only tested this with a numerical target as that is my use case.

Categories