I want to use the value of a variable to access an object.
Let's say I have an object named myobject.
I want to fill a variable with this name and use the variable to access the object.
Example:
var objname = 'myobject';
{objname}.value = 'value';
Global:
myObject = { value: 0 };
anObjectName = "myObject";
this[anObjectName].value++;
console.log(this[anObjectName]);
Global: v2
var anObjectName = "myObject";
this[anObjectName] = "myvalue"
console.log(myObject)
Local: v1
(function() {
var scope = this;
if (scope != arguments.callee) {
arguments.callee.call(arguments.callee);
return false;
}
scope.myObject = { value: 0 };
scope.anObjectName = "myObject";
scope[scope.anObjectName].value++;
console.log(scope.myObject.value);
})();
Local: v2
(function() {
var scope = this;
scope.myObject = { value: 0 };
scope.anObjectName = "myObject";
scope[scope.anObjectName].value++;
console.log(scope.myObject.value);
}).call({});
alert(this === window).window object called objname which is then referenced via this ... you could substitute window for this in the second example and everything would still work. :-)arguments.callee is deprecated, but it's a very clever implementation nonetheless -- and it doesn't litter the global scope. +1objname as a property of the function itself. It can fail for recursive functions. Not sure how this can be used in the real world.The object exists in some scope, so you can almost always access the variable via this syntax:
var objname = "myobject";
containing_scope_reference[objname].some_property = 'some value';
The only place where this gets tricky is when you are in a closed scope and you want access to a top-level local variable. When you have something like this:
(function(){
var some_variable = {value: 25};
var x = "some_variable";
console.log(this[x], window[x]); // Doesn't work
})();
You can get around that by using eval instead to access the current scope chain ... but I don't recommend it unless you've done a lot of testing and you know that that's the best way to go about things.
(function(){
var some_variable = {value: 25};
var x = "some_variable";
eval(x).value = 42;
console.log(some_variable); // Works
})();
Your best bet is to have a reference to a name in an always-going-to-be-there object (like this in the global scope or a private top-level variable in a local scope) and put everything else in there.
Thus:
var my_outer_variable = {};
var outer_pointer = 'my_outer_variable';
// Reach my_outer_variable with this[outer_pointer]
// or window[outer_pointer]
(function(){
var my_inner_scope = {'my_inner_variable': {} };
var inner_pointer = 'my_inner_variable';
// Reach my_inner_variable by using
// my_inner_scope[inner_pointer]
})();
You could use eval:
eval(variablename + ".value = 'value'");
eval considered evil? If not I might use it. Because it is a global right now but I wanted to move it into a function to clean up stuff.eval can execute.eval, in my opinion. We have to make sure the variable is clean, though.myVar[objname].value?I think Shaz's answer for local variables is hard to understand, though it works for non-recursive functions. Here's another way that I think it's clearer (but it's still his idea, exact same behavior). It's also not accessing the local variables dynamically, just the property of the local variable.
Essentially, it's using a global variable (attached to the function object)
// Here's a version of it that is more straight forward.
function doIt() {
doIt.objname = {};
var someObject = "objname";
doIt[someObject].value = "value";
console.log(doIt.objname);
})();
Which is essentially the same thing as creating a global to store the variable, so you can access it as a property. Creating a global to do this is such a hack.
Here's a cleaner hack that doesn't create global variables, it uses a local variable instead.
function doIt() {
var scope = {
MyProp: "Hello"
};
var name = "MyProp";
console.log(scope[name]);
}
If object is in some namespace ie. Company.Module.Components.Foo you can use this function:
CoffeeScript:
objByName: (name, context = window) ->
ns = name.split "."
func = context
for n, i in ns
func = func[n]
return func
Resulted Js:
objByName: function(name, context) {
var func, i, n, ns, _i, _len;
if (context == null) {
context = window;
}
ns = name.split(".");
func = context;
for (i = _i = 0, _len = ns.length; _i < _len; i = ++_i) {
n = ns[i];
func = func[n];
}
return func;
}
Then you can create a new object or do whatever. Note the parenthises through.
var o = new (objByName('Company.Module.Components.Foo'))
objByName('some.deeply.nested.object').value
This idea is borrowed from similar question: How to execute a JavaScript function when I have its name as a string
One of the challenges I had with the answers is that it assumed that the object was a single level. For example,
const testObj = { testKey: 'testValue' }
const refString = 'testKey';
const refObj = testObj[refString];
works fine, but
const testObj = { testKey:
{ level2Key: 'level2Value' }
}
const refString = 'testKey.level2Key';
const refObj = testObj[refString];
does not work.
What I ended up doing was building a function to access multi-level objects:
objVar(str) {
let obj = this;
const parts = str.split('.');
for (let p of parts) {
obj = obj[p];
}
return obj;
}
In the second scenario, then, I can pass the string to this function to get back the object I'm looking for:
const testObj = { testKey:
{ level2Key: 'level2Value' }
}
const refString = 'testObj.testKey.level2Key';
const refObj = objVar[refString];
If you already know the list of the possible varible names then try creating a new Object(iconObj) whose properties name are same as object names, Here in below example, iconLib variable will hold two string values , either 'ZondIcons' or 'MaterialIcons'. propertyName is the property of ZondIcons or MaterialsIcon object.
const iconObj = {
ZondIcons,
MaterialIcons,
}
const objValue = iconObj[iconLib][propertyName]