Javascript使用变量作为对象名称


91

我想使用变量的值来访问对象。

假设我有一个名为myobject的对象。

我想用此名称填充变量,然后使用该变量访问对象。

例:

var objname = 'myobject';
{objname}.value = 'value';

Answers:


125

全球:

myObject = { value: 0 };
anObjectName = "myObject";
this[anObjectName].value++;

console.log(this[anObjectName]);

全球:v2

var anObjectName = "myObject";
this[anObjectName] = "myvalue"

console.log(myObject)

本地: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);
})();

本地:v2

(function() {  
    var scope = this;

    scope.myObject = { value: 0 };
    scope.anObjectName = "myObject";
    scope[scope.anObjectName].value++;

    console.log(scope.myObject.value);    
}).call({});

@Shaz-两者实际上都引用相同的作用域;-)(假设它们在浏览器中执行) alert(this === window)
肖恩·维埃拉

1
@PeeHaa -在本地例如在设置一个变量window调用的对象objname,然后通过参考this...你可以代替windowthis在第二个例子中,一切都仍然坚持工作。:-)
肖恩·维埃拉

1
@SeanVieira:看一下更新后的示例。希望这现在可以正常工作。
沙兹

1
@Shaz-arguments.callee已过时,但它是一个非常聪明的实现-并且不会乱扔全局范围。+1
肖恩·维埃拉

1
它可能不会污染全局范围,但会创建一个对象,该函数每次调用都会共享该对象。您的函数是objname函数本身的属性。对于递归函数,它可能会失败。不确定如何在现实世界中使用它。
Juan Mendes 2012年


9

它是全局变量吗?如果是这样,则它们实际上是window对象的一部分,因此您可以这样做window[objname].value

如果它是某个函数的本地函数,那么我认为没有一种执行所需操作的好方法。


8

对象存在于某个范围内,因此您几乎总是可以通过以下语法访问变量:

var objname = "myobject";
containing_scope_reference[objname].some_property = 'some value';

唯一棘手的地方是当您处于封闭范围内并且想要访问顶级局部变量时。当你有这样的事情:

(function(){
    var some_variable = {value: 25};
    var x = "some_variable";
    console.log(this[x], window[x]); // Doesn't work
})();

可以通过使用eval来访问当前的作用域链来解决该问题……但是,除非您进行了大量测试并且您知道,否则我不建议您这样做这是处理问题的最佳方法,。

(function(){
    var some_variable = {value: 25};
    var x = "some_variable";
    eval(x).value = 42;
    console.log(some_variable); // Works
})();

最好的办法是有一个名称的引用始终持续到待有物体(如this在全局范围内或在局部范围内的私人顶级变量),并把一切都在那里东西。

从而:

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

7

您可以使用eval

eval(variablename + ".value = 'value'");

eval考虑evil吗?如果没有,我可能会使用它。因为它现在是全球性的,但我想将其移至一个用于清理内容的函数中。
PeeHaa

1
大声笑。如果变量名来自用户输入,请确保对其进行验证,以使其不包含任何eval可执行的JS代码。
Midas

1
eval我认为,这是的少数合法使用之一。不过,我们必须确保变量是干净的。
维·莫里森

2
是的,这不是真正的问题。但是看看Shaz的答案。我认为这是一个更干净的解决方案。
Midas

2
@PeeHaa:如果您正在考虑移动它,为什么不将其移动到已知对象的属性中,那么您可以执行类似的操作myVar[objname].value
JW。

6

通常,您不能执行此操作,除了在窗口范围内,您可以在其中编写 window[objname].value = 'value';


4

我认为Shaz对于局部变量的答案虽然很难用于非递归函数,但很难理解。我认为这是更清楚的另一种方式(但这仍然是他的想法,行为完全相同)。它也不动态地访问局部变量,而只是局部变量的属性。

本质上,它使用全局变量(附加到函数对象)

// 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);
})();

这与创建用于存储变量的全局变量基本相同,因此您可以将其作为属性来访问。创建一个全局的来做到这一点就是这样的黑客。

这是一个更干净的技巧,它不会创建全局变量,而是使用局部变量。

function doIt() {
  var scope = {
     MyProp: "Hello"
  };
  var name = "MyProp";
  console.log(scope[name]);
}

参见Javascript:将字符串解释为对象引用吗?


1

如果对象在某个名称空间中,即。Company.Module.Components.Foo您可以使用此功能:

CoffeeScript:

objByName: (name, context = window) ->
    ns = name.split "."
    func = context
    for n, i in ns
        func = func[n]
    return func

结果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;
}

然后,您可以创建一个新对象或执行任何操作。记下括号。

var o = new (objByName('Company.Module.Components.Foo'))
objByName('some.deeply.nested.object').value

这个想法是从类似的问题中借用的:当我将其名称作为字符串时如何执行JavaScript函数


1
let players = [];
players[something] = {};
players[something].somethingElse = 'test';
console.log(players); 

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


0

使用window [objname]时,请确保objname是全局变量。否则,它将在某个时间工作,有时会失败。window [objname] .value。


0

我在回答中遇到的挑战之一是,它假设对象是单个级别。例如,

const testObj = { testKey: 'testValue' }
const refString = 'testKey';
const refObj = testObj[refString];

工作正常,但是

const testObj = { testKey:
                  { level2Key: 'level2Value' }
                }
const refString = 'testKey.level2Key';
const refObj = testObj[refString];

不起作用。

我最终要做的是构建一个访问多级对象的函数:

objVar(str) {
    let obj = this;
    const parts = str.split('.');
    for (let p of parts) {
        obj = obj[p];
    }
    return obj;
}

然后,在第二种情况下,我可以将字符串传递给此函数以找回我要查找的对象:

const testObj = { testKey:
                  { level2Key: 'level2Value' }
                }
const refString = 'testObj.testKey.level2Key';
const refObj = objVar[refString];

0

您可以通过以下方式设置对象属性:

var obj = {};
obj.whateverVarName = 'yourVal';
console.log(obj);


0

如果您已经知道可能的变量名称列表,则尝试创建一个新的Object(iconObj),其属性名称与对象名称相同。在下面的示例中,这里的iconLib变量将包含两个字符串值,即'ZondIcons'或'MaterialIcons' 。propertyName是ZondIcons或MaterialsIcon对象的属性。

   const iconObj = {
    ZondIcons,
    MaterialIcons,
  }
  const objValue = iconObj[iconLib][propertyName]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.