105

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';
PeeHaa
  • 71,436
  • 58
  • 190
  • 262

15 Answers15

137

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({});
Community
  • 1
  • 1
Shaz
  • 15,637
  • 3
  • 41
  • 59
  • @Shaz -- both of those reference the same scope actually ;-) (Assuming they are executed in a browser.) `alert(this === window)`. – Sean Vieira May 21 '11 at 22:48
  • @Sean: They are. And they do? – PeeHaa May 21 '11 at 22:49
  • 1
    @PeeHaa - The **Local** example sets a variable on the `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. :-) – Sean Vieira May 21 '11 at 22:56
  • 1
    @SeanVieira: Take a look at the updated example. Hopefully this works correctly now. – Shaz May 21 '11 at 23:18
  • 1
    @Shaz -- `arguments.callee` is deprecated, but it's a *very* clever implementation nonetheless -- **and** it doesn't litter the global scope. +1 – Sean Vieira May 21 '11 at 23:24
  • 1
    It may not be polluting the global scope, but it's creating an object that is shared by every invocation of the function. Your function is holding `objname` as a property of the function itself. It can fail for recursive functions. Not sure how this can be used in the real world. – Ruan Mendes Jun 08 '12 at 17:45
  • @Sean @Juan I've updated version 2 which does not use `arguments.callee`. – Shaz Aug 31 '15 at 23:09
  • @Shaz can we use the `Function` keyword here?If yes then please explain how.I was thinking of something like in here. http://stackoverflow.com/questions/36078655/extract-call-javascript-function-defined-in-the-onclick-html-attribute-of-an-e – techie_28 May 18 '16 at 09:48
45

Use square bracket around variable name.

var objname = 'myobject';
{[objname]}.value = 'value';
10

Is it a global variable? If so, these are actually part of the window object, so you can do window[objname].value.

If it's local to a function, I don't think there's a good way to do what you want.

JW.
  • 50,691
  • 36
  • 115
  • 143
9

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]
})();
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
8

You could use eval:

eval(variablename + ".value = 'value'");
Midas
  • 7,012
  • 5
  • 34
  • 52
  • Isn't `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. – PeeHaa May 21 '11 at 22:38
  • 1
    Lol. If the variable name comes from user input, make sure you validate it, so that it doesn't contain any JS code that `eval` can execute. – Midas May 21 '11 at 22:42
  • @Midas: it doesn't come directly from user input. But from an HTML element's data content. Which the user of course can manipulate. However I don't see what's so bad if the user can execute his own JS code. It only get executed on the client or am I missing something? – PeeHaa May 21 '11 at 22:46
  • 1
    This is one of the few legitimate uses of `eval`, in my opinion. We have to make sure the variable is clean, though. – Levi Morrison May 21 '11 at 22:48
  • 2
    Yes it's not really a problem. But take a look at the answer from Shaz. I think that's a more clean solution. – Midas May 21 '11 at 22:49
  • 2
    @PeeHaa: If you're considering moving it, why not move it into a property of a known object, so you can do something like `myVar[objname].value`? – JW. May 22 '11 at 00:05
6

You can't do this in general, except at the window scope, where you can write window[objname].value = 'value';

Neil
  • 54,642
  • 8
  • 60
  • 72
4

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]);
}

See Javascript: interpret string as object reference?

Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
4

Square brackets can be used to make key dynamic like this

var myObjKey = "key";

var obj = {[myObjKey] : "value" };
console.log(obj); // => {key: 'value'}

var anotherObj = {["justString"] : "value" };
console.log(anotherObj ); // => {justString: 'value'}
Uzair Ali
  • 510
  • 14
  • 32
3
let players = [];
players[something] = {};
players[something].somethingElse = 'test';
console.log(players); 

-> [ something: { somethingElse: 'test' } ];

1

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

Community
  • 1
  • 1
0

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];
0

You can set an objects property this way:

var obj = {};
obj.whateverVarName = 'yourVal';
console.log(obj);
Stephan T.
  • 5,843
  • 3
  • 20
  • 42
ThisisFish
  • 416
  • 1
  • 6
  • 14
0

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]
Sumer
  • 2,687
  • 24
  • 24
-1

When using the window[objname], please make sure the objname is global variables. Otherwise, will work sometime, and fail sometimes. window[objname].value.

lyon819
  • 89
  • 1
  • 2
-2
var micro=[{'test':'hello'}];

var device = 'test';

console.log(micro[device]);
alfonsoolavarria
  • 1,141
  • 11
  • 11