How can I access myobject[path][to][obj] via a string path.to.obj? I want to call a function Settings.write('path.to.setting', 'settingValue') which would write 'settingValue' to settingObj[path][to][setting]. How can I do this without eval()?
I finally figured it out around the same time as one of the users below answered it. I'll post mine here with documentation on how it works if anyone is interested.
(function(){
var o = {}, c = window.Configure = {};
c.write = function(p, d)
{
// Split the path to an array and assaign the object
// to a local variable
var ps = p.split('.'), co = o;
// Iterate over the paths, skipping the last one
for(var i = 0; i < ps.length - 1; i++)
{
// Grab the next path's value, creating an empty
// object if it does not exist
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
// Assign the value to the object's last path
co[ps[ps.length - 1]] = d;
}
c.read = function(p)
{
var ps = p.split('.'), co = o;
for(var i = 0; i < ps.length; i++)
{
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
return co;
}
})();
The reason I was having problems is you have to skip the last path. If you include the last path, you end up just assigning an arbitrary object.
You can use str.split() for that:
path = pathString.split('.');
settingObj[path[0]][path[1]][path[2]] = settingValue;
str.split() will separate the variable into an array, split at the locations of the character you specify.
This is just the root of the operation of course, and assumes proper input.
Edit: Since the paths need to be of variable length, here's an updated version edited from the syntax you've shown above:
(function(){
var o = {}, c = window.Configure = {};
c.write = function(p, d)
{
var ps = p.split('.'), co = o;
for(var i = 0; i < ps.length - 1; i++)
{
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
co[ps[ps.length-1]] = d;
}
c.read = function(p)
{
var ps = p.split('.'), co = o;
for(var i = 0; i < ps.length; i++)
{
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
return co;
}
c.write('path.to.property', 'setting');
alert(c.read('path.to.property'));
})();
Your variable co contains a reference to your property, but when you update the value of co with co = p you are just overwriting the value of co, not the value of the property. You need to keep a reference to the last key, and use that key to set the value:
http://jsfiddle.net/gilly3/a2p8m/1/
c.write = function(p, d)
{
var ps = p.split('.'), co = o, key;
for(var i = 0; i < ps.length; i++)
{
if (key)
{
co = (key in co) ? co[key] : co[key] = {};
}
key = ps[i];
}
co[key] = d;
console.log(co);
console.log(o);
}
You may want to use key in co instead of just doing a "truthy" check. Otherwise, a value of 1, will be retained while a value of 0 will be overwritten with {}. Then again, either of those values would result in a runtime error for the above code, since you can't write a property onto a number. Best would be to check typeof co[key].
co = co[key] && /object|function/.test(typeof co[key]) ? co[key] : co[key] = {};
(I know I'm a little late with my answer, but I figure after putting all that effort in typing with my thumbs, I might as well include it anyway)
I suspect you are encountering a grouping error. Try moving the end paren in your ternary expression to the end of the line:
co = (co[ps[i]] ? co[ps[i]] : co[ps[i]] = {});
I'd test this myself but I'm answering from my mobile and jsfiddle is tedious when typing with just thumbs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With