在JavaScript中使用动态变量名称


344

在PHP中,您可以执行以下令人惊奇/可怕的事情:

$a = 1;
$b = 2;
$c = 3;
$name = 'a';
echo $$name;
// prints 1

有没有办法用Java做类似的事情?

例如,如果我有一个名称,var name = 'the name of the variable';可以得到对变量的引用name吗?


2
可能是对stackoverflow.com/questions/724857/…stackoverflow.com/questions/1664282/…的欺骗,但是在这里,IMO更好地接受了答案。
眼神

这回答了你的问题了吗?Javascript中的“变量”变量?。那里被接受的答案比这里的答案要好,因为它显示了如何做,但也正确地警告说,几乎总有一种更好的方法来做您想做的事情。请参阅meta上的XY问题
ggorlen

Answers:


353

由于ECMA-/ JavaScript是所有关于ObjectsContexts(其也somekind的对象的),每个变量被存储在这样的被称为可变(或在功能的情况下,激活对象)。

因此,如果您创建这样的变量:

var a = 1,
    b = 2,
    c = 3;

全局范围(= NO函数上下文)中,您将这些变量隐式写入全局对象(=window在浏览器中)。

可以使用“点”或“括号”表示法来访问它们:

var name = window.a;

要么

var name = window['a'];

这仅适用于在这种特定情况下的全局对象,因为变量对象中的全局对象window对象本身。在函数的上下文中,您没有直接访问Activation Object的权限。例如:

function foobar() {
   this.a = 1;
   this.b = 2;

   var name = window['a']; // === undefined
   alert(name);
   name = this['a']; // === 1
   alert(name);
}

new foobar();

new创建一个自定义对象(上下文)的新实例。没有new该功能的范围也将是global(= window)。此示例将分别警告undefined1。如果我们替换this.a = 1; this.b = 2为:

var a = 1,
    b = 2;

两个警报输出均未定义。在这种情况下,变量ab将存储在foobar无法访问的激活对象中(我们可以通过调用a和直接访问它们b)。


1
另一个很酷的事情是,您可以通过这种方式为任何全局级别的函数添加回调(开始/结束)。
抗毒剂2012年

5
但是,如果我的动态变量在函数中是局部的,该怎么办?例如:function boink(){var a = 1; //这将不起作用var dynamic = this ['a']; //这也不起作用var dynamic = ['a']; }
Kokodoko

@Kokodoko-因为不是“上下文”或对函数执行上下文的引用(无法引用执行上下文,因此ECMA-262禁止这样做)。是通过函数的调用方式(或通过bind)来设置的,它只是一个与可访问它的执行上下文无关的对象。
RobG

如果您需要访问嵌套属性退房stackoverflow.com/questions/4244896/...
溴先生

用括号符号指向我正确的方向。只停留在思考点表示法。
安德鲁(Andrew)

149

eval 是一种选择。

var a = 1;
var name = 'a';

document.write(eval(name)); // 1

19
不,不应该这样,因为评估是邪恶的。永远不要使用eval!
EasyBB 2014年

52
@EasyBB-如果您要说永远不要使用某些东西,那么我将无济于事。除了eval()之外,我无法想到其他任何方式来完成我正在做的事情
Rampant Creative Group 2014年

4
Eval对最终用户构成攻击风险,从技术上讲,它不是邪恶的,而是在丢失案件中被误解和滥用。我看过php响应,其中包含文字变量,然后使用eval运行它。尽管在这种情况下不应该使用此方法,因为有更好的方法。因为总体上有更好的方法,所以根本不应该使用这个问题,我相信我们很多人都知道这一点。
EasyBB 2014年

2
通过javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval ---“让我们考虑最经常使用eval的参数:1)它需要编译,因此运行缓慢2)如果恶意脚本被发现进入eval参数了吗?3)看起来很难看4)它继承了执行上下文以及对其调用范围的绑定”
mattLummus

1
以下是使用eval创建动态变量的方法:stackoverflow.com/a/13291766/5528600
am2124429

80

您可以使用window对象进行操作。

window['myVar']

window 引用了您正在使用的所有全局变量和全局函数。


28
不用说,这比eval()更安全。
Cray

45

只是不知道一个糟糕的答案会得到这么多的选票。答案很简单,但您会使它变得复杂。

// If you want to get article_count
// var article_count = 1000;
var type = 'article';
this[type+'_count'] = 1000;  // in a function we use "this";
alert(article_count);

13
“在函数中,我们使用this”-如果您想以这种方式访问全局变量,最好是显式并使用window对象,而不是thisthis是模棱两可的。
MrWhite

1
但是在函数内部,如果您在另一个变量中有名称,则不能使用this或其他任何方式type从示例中访问变量:function test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type')将显示article,而不是something else。这就是“复杂答案”的解释。
奥拉夫

28
a = 'varname';
str = a+' = '+'123';
eval(str)
alert(varname);

尝试这个...


27

这是一个例子:

for(var i=0; i<=3; i++) {
    window['p'+i] = "hello " + i;
}

alert(p0); // hello 0
alert(p1); // hello 1
alert(p2); // hello 2
alert(p3); // hello 3

另一个例子 :

var myVariable = 'coco';
window[myVariable] = 'riko';

alert(coco); // display : riko

因此,myVariable的值“ coco ” 成为变量coco

因为全局作用域中的所有变量都是Window对象的属性。


14

在Javascript中,您可以使用所有属性都是键值对的事实。jAndy已经提到了这一点,但是我不认为他的回答表明了如何利用它。

通常,您不是试图创建一个变量来保存变量名,而是试图生成变量名然后使用它们。PHP使用$$var符号来做到这一点,但是Javascript不需要这样做,因为属性键可以与数组键互换。

var id = "abc";
var mine = {};
mine[id] = 123;
console.log(mine.abc);

给出123。通常您想要构造变量,这就是为什么存在间接的原因,因此您也可以采用其他方法。

var mine = {};
mine.abc = 123;
console.log(mine["a"+"bc"]);

1
var someJsonObj = {}; 循环.... for(var i = 0; i <= 3; i ++){someJsonObj [i] = []; },但我可以做任何事。因此动态生成的变量都位于someJsonObj中,以方便参考。
rajeev

5

2019年

TL; DR

  • eval 操作员可以在其调用的上下文中运行字符串表达式,并从该上下文返回变量;
  • literal object理论上可以通过write:来做到这一点{[varName]},但是它被定义阻塞了。

因此,我遇到了这个问题,这里的每个人都在四处闲逛,没有提出真正的解决方案。但是@Axel Heider的接洽很好。

解决方法是eval。几乎是最被遗忘的运营商。(以为是最多的with()

eval运算符可以在其调用的上下文中动态运行表达式。并返回该表达式的结果。我们可以使用它在函数的上下文中动态返回变量的值。

例:

function exmaple1(){
   var a = 1, b = 2, default = 3;
   var name = 'a';
   return eval(name)
}

example1() // return 1


function example2(option){
  var a = 1, b = 2, defaultValue = 3;

  switch(option){
    case 'a': name = 'a'; break;
    case 'b': name = 'b'; break;
    default: name = 'defaultValue';
  }
  return eval (name);
}

example2('a') // return 1
example2('b') // return 2
example2() // return 3

请注意,我总是明确地编写表达式eval将运行。为避免代码中出现不必要的意外。eval非常强壮 但我确定你已经知道

顺便说一句,如果合法,我们可以literal object用来捕获变量名和值,但是我们不能将计算出的属性名和属性值速记结合起来,可惜,这是无效的

functopn example( varName ){
    var var1 = 'foo', var2 ='bar'

    var capture = {[varName]}

}

example('var1') //trow 'Uncaught SyntaxError: Unexpected token }`

这是一个快速的解决方案,但这是一个不好的做法,因为它不安全并且会降低性能,因为JS引擎无法优化该方法。
迭戈·奥尔蒂斯

很棒的解决方案
Rohit Parte,

4

如果您不想使用诸如window或global(节点)之类的全局对象,则可以尝试如下操作:

var obj = {};
obj['whatever'] = 'There\'s no need to store even more stuff in a global object.';

console.log(obj['whatever']);

3

我需要动态绘制多个FormData,并且对象运行良好

var forms = {}

然后在需要创建表格数据的地方循环

forms["formdata"+counter]=new FormData();
forms["formdata"+counter].append(var_name, var_value);

谢谢...这完全救了我!this。$ refs ['listView'+ index] .nativeView.animate({..})我需要像这样的refs中的变量。$ refs.listView1 listView2等等……
Meiki Neumann

2

对于需要导出动态命名变量的用户来说,这是一种替代方法

export {
  [someVariable]: 'some value',
  [anotherVariable]: 'another value',
}

// then.... import from another file like this:
import * as vars from './some-file'

另一种选择是简单地创建一个其键被动态命名的对象

const vars = { [someVariable]: 1, [otherVariable]: 2 };

// consume it like this
vars[someVariable];

1

他们的意思是不,你不能。没有办法完成它。所以有可能你可以做这样的事情

function create(obj, const){
// where obj is an object and const is a variable name
function const () {}

const.prototype.myProperty = property_value;
// .. more prototype

return new const();

}

具有与ECMAScript 5中实现的功能相同的创建功能。


4
当心:const是ES6中的关键字
Tejas Manohar 2015年

4
...在此之前是未来保留字
TJ Crowder 2015年

eval操作员
pery mimon

1

eval()在我的测试中不起作用。但是可以向DOM树添加新的JavaScript代码。因此,这是一个添加新变量的函数:

function createVariable(varName,varContent)
{
  var scriptStr = "var "+varName+"= \""+varContent+"\""

  var node_scriptCode = document.createTextNode( scriptStr )
  var node_script = document.createElement("script");
  node_script.type = "text/javascript"
  node_script.appendChild(node_scriptCode);

  var node_head = document.getElementsByTagName("head")[0]
  node_head.appendChild(node_script);
}

createVariable("dynamicVar", "some content")
console.log(dynamicVar)

2
小的改进,它是更好地使用var node_head = document.getElementsByTagName("head")[0],而不是ID的,因为没有人给出了一个id="head"<head>:-)
ddlab

我愿意:)但是,谢谢,现在我终于可以删除这个'id =“ head”的东西
Axel Heider

1
这似乎是创建全局变量的一种过于复杂的方式?(...这如何回答问题?)
怀特先生

天才:) eval是解决方案。即使您的代码不起作用
pery mimon

1

尽管这是一个可接受的答案,但我想补充一点:

在ES6中,使用let 不起作用

/*this is NOT working*/
let t = "skyBlue",
    m = "gold",
    b = "tomato";

let color = window["b"];
console.log(color);

但是使用var 作品

/*this IS working*/
var t = "skyBlue",
    m = "gold",
    b = "tomato";

let color = window["b"];
console.log(color);

我希望这可能对某些人有用。


1
同样适用于 const

1
真正。但是您可以使用变量创建对象,然后从中选择变量:const vars = { t, m, b }; console.log(vars['b'])。否则eval也可以。
Fabian von Ellerts

0

使用对象也很棒。

var a=123
var b=234
var temp = {"a":a,"b":b}
console.log(temp["a"],temp["b"]);
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.