在 JavaScript 中使用动态变量名称 [duplicate]

Use dynamic variable names in JavaScript [duplicate]

提问人:Finbarr 提问时间:2/25/2011 最后编辑:VLAZFinbarr 更新时间:3/2/2023 访问量:705173

问:

在PHP中,你可以做这样令人惊奇/可怕的事情:

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

有没有办法用 Javascript 做这样的事情?

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

JavaScript的

评论

2赞 ggorlen 12/7/2019
这回答了你的问题吗?Javascript 中的“变量”变量?.那里公认的答案比这里的答案更好,因为它显示了如何去做,但也正确地警告说,几乎总是有更好的方法来做你想做的任何事情。请参阅 meta 上的 XY 问题
0赞 pilchard 2/19/2023
这回答了你的问题吗?什么时候适合使用分号?

答:

105赞 JohnP 2/25/2011 #1

您可以使用 window 对象来获取它。

window['myVar']

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

评论

33赞 Cray 2/25/2011
不用说,这个比 eval() 更安全。
0赞 binpy 9/1/2020
看起来像 .这很有帮助。windowstate
0赞 Bu Saeed 4/16/2022
但是,当我想使用本地变量时呢?
1赞 JohnP 4/16/2022
@BuSaeed 不确定我是否理解,如果变量已经是本地范围,您不能按名称引用它吗?您可能应该问一个新问题,因为这是一个具有不同含义的旧问题。
169赞 erickb 2/25/2011 #2

eval是一种选择。

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

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

警告:请注意,如果您不知道自己在做什么,则不建议使用该功能,因为它会带来多个安全问题。除非绝对必要,否则使用其他东西。有关更多信息,请参见 MDN 页面的 eval 页面eval()

评论

29赞 EasyBB 1/19/2014
不,它不应该,因为 eval 是邪恶的。永远不要使用 eval!
75赞 Rampant Creative Group 3/25/2014
@EasyBB - 如果你要说永远不要使用某些东西,我无法解释为什么。我有一种情况,除了 eval() 之外,我想不出任何其他方法来完成我正在做的事情
5赞 EasyBB 3/25/2014
Eval 对最终用户构成了攻击的风险,从技术上讲,它不是邪恶的,而是在丢失的情况下被误解和滥用。我见过 php 响应,其中包含文字变量,然后使用 eval 运行它。尽管在这种情况下不应使用这,因为有更好的方法。手头的这个问题根本不应该使用,因为总体上有更好的方法,我相信我们很多人都知道这一点。
3赞 mattLummus 5/13/2015
通过 javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval--- “让我们考虑一下最常反对使用 eval 的论点:1) 它需要编译,因此速度很慢 2) 如果恶意脚本进入了 eval 参数怎么办?3)它看起来很丑 4)它继承了执行上下文和调用它的作用域的绑定”
1赞 am2124429 3/21/2016
以下是使用 eval 创建动态变量的方法: stackoverflow.com/a/13291766/5528600
407赞 jAndy 2/25/2011 #3

由于 ECMA-/Javascript 是关于 和(它们也是某种对象),因此每个变量都存储在称为 Variable- (或者如果是函数,则为 Activation 对象)中。ObjectsContexts

因此,如果您创建如下变量:

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

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

可以使用“点”或“括号”表示法访问这些内容:

var name = window.a;

var name = window['a'];

这仅适用于此特定实例中的全局对象,因为全局对象的变量对象是对象本身。在函数的 Context 中,您无权直接访问 Activation 对象。例如:window

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

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

new foobar();

new创建自定义对象 (Context) 的新实例。如果没有函数的范围,也会是 (=window)。此示例将分别发出警报和警报。如果我们用以下方法替换:newglobalundefined1this.a = 1; this.b = 2

var a = 1,
    b = 2;

两个警报输出都是未定义的。在这种情况下,变量 and 将存储在 激活对象中,我们无法访问该对象(当然,我们可以通过调用 和 直接访问它们)。abfoobarab

评论

1赞 antitoxic 8/7/2012
另一件很酷的事情是,通过这种方式,您可以为任何全局级别函数添加回调(开始/结束)。
8赞 Kokodoko 10/28/2013
但是,如果我的动态变量在函数中是局部的呢?例如: function boink() { var a = 1; // 这不起作用 var dynamic = this['a']; // 这也不起作用 var dynamic = ['a']; }
0赞 RobG 5/13/2015
@Kokodoko - 因为这不是“上下文”或对函数执行上下文的引用(无法引用执行上下文,这是 ECMA-262 所禁止的)。这是由函数的调用方式(或绑定)设置的,它只是一个对象,与可访问它的执行上下文无关。
0赞 Mr Br 6/22/2015
如果您需要访问嵌套属性,请查看 stackoverflow.com/questions/4244896/...
1赞 Andrew 3/3/2017
用括号符号为我指明了正确的方向。被困在只想点符号。
29赞 amitchd 2/25/2011 #4
a = 'varname';
str = a+' = '+'123';
eval(str)
alert(varname);

试试这个...

0赞 Alfgaar 11/24/2012 #5

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

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 中实现的 create 函数。

评论

4赞 Tejas Manohar 11/17/2015
注意:const 是 ES6 中的一个关键字
6赞 T.J. Crowder 12/10/2015
...在此之前是未来的保留词
0赞 pery mimon 1/5/2019
有操作员eval
0赞 Axel Heider 10/6/2014 #6

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赞 ddlab 11/10/2014
小改进,最好使用而不是ID,因为没有人给:-)var node_head = document.getElementsByTagName("head")[0]id="head"<head>
0赞 Axel Heider 5/4/2015
我:)但是谢谢,现在我终于可以删除这个'id=“head”的东西了
1赞 MrWhite 8/24/2015
这似乎是创建全局变量的一种过于复杂的方法?!(...这如何回答这个问题?
0赞 pery mimon 1/5/2019
天才:)eval 是解决方案。即使您的代码不起作用
21赞 David Newcomb 11/27/2014 #7

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

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

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

给 123。通常你想构造变量,这就是为什么有间接的原因,所以你也可以反过来做。

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

评论

1赞 rajeev 4/7/2017
var someJsonObj = {};在循环中......for(var i=0; i<=3; i++) { someJsonObj[i] = []; },但我可以是任何东西。所以动态生成的变量,都位于 someJsonObj 中,以便于参考。
62赞 Terry Lin 1/21/2015 #8

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

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

评论

15赞 MrWhite 8/24/2015
“in a function we use ” - 如果你想以这种方式访问全局变量,最好是显式的,使用对象,而不是. 是模棱两可的。thiswindowthisthis
2赞 Orafu 1/7/2020
但是在函数内部,如果变量的名称在另一个变量中,则不能使用 或其他任何东西来访问示例中的变量: 将显示 ,而不是 。这就是“复杂答案”所解释的。thistypefunction test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type')articlesomething else
1赞 celticminstrel 6/29/2020
这是行不通的。如果将它放在函数中并使用对象(使用运算符或点表示法)调用它,则它会输出到警报框。undefinednew
0赞 GavinBelson 1/29/2021
在 Express.js 路由中效果很好
0赞 DemiA 10/23/2021
谢谢@Terry,这在 Vue 中完美运行。如果声明了多个数据属性,并且需要一种方法来决定要面向哪个数据属性,则只需按如下方式传递属性名称:changeProperty(propertyName) { this[propertyName] = 1; } changeProperty("bar") changeProperty("baz")
33赞 Azodium 1/25/2015 #9

这是一个例子:

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 对象的属性。

10赞 Brent Barbata 1/30/2015 #10

如果你不想使用像 window 或 global(节点)这样的全局对象,你可以尝试如下操作:

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

console.log(obj['whatever']);
6赞 Talha 9/18/2017 #11

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

var forms = {}

然后在我的循环中,无论我需要在哪里创建我使用的表单数据

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

评论

0赞 Mehdi Nourollah 3/1/2020
谢谢。。。它完全救了我!this.$refs['listView' + index].nativeView.animate({..})我需要像这样.$refs.listView1、listView2 等引用中的变量......
7赞 pery mimon 1/5/2019 #12

2019

TL;博士

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

所以我遇到了这个问题,这里的每个人都只是玩弄,没有带来真正的解决方案。但@Axel海德有一个很好的方法。

解决方案是 . 几乎大多数被遗忘的操作员。(认为大多数是evalwith() )

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

例:

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 }`

评论

1赞 Diego Ortiz 1/31/2020
这是一个快速的解决方案,但这是一种不好的做法,因为它不安全并且会降低性能,因为 JS 引擎无法优化该方法。
0赞 Gust van de Wal 12/14/2020
“default”是 JavaScript 中的保留字。不应将其用作变量名称
1赞 Steve Jiang 3/20/2019 #13

使用对象也很棒。

var a=123
var b=234
var temp = {"a":a,"b":b}
console.log(temp["a"],temp["b"]);
1赞 enxaneta 3/23/2019 #14

虽然这有一个公认的答案,但我想补充一个意见:

在 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);

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

评论

2赞 4/19/2019
这同样适用于const
1赞 Fabian von Ellerts 10/3/2019
真。但是您可以使用变量创建一个对象,然后从那里选择变量:.否则也有效。const vars = { t, m, b }; console.log(vars['b'])eval
0赞 Gust van de Wal 12/14/2020
@FabianvonEllerts 你发表评论的目的是什么?这个答案只是为了解决块级作用域(&)和全局()作用域(&)之间的区别。您的评论与此无关,而是作为单独的答案。letconstwindowvarfunction
3赞 JeanAlesi 5/24/2019 #15

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

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赞 FZs 11/13/2020
为什么你需要/这样做?为什么不简单地创建一个对象并访问其属性呢?此外,无法导出动态名称,除非您将对象导出为默认名称...importexport
-1赞 Rishu Ranjan 9/2/2020 #16

最好使用创建命名空间并在其中声明一个变量,而不是将其添加到全局对象中。我们还可以创建一个函数来获取和设置值

请参阅以下代码片段:

//creating a namespace in which all the variables will be defined.
var myObjects={};

//function that will set the name property in the myObjects namespace
function setName(val){
  myObjects.Name=val;
}

//function that will return the name property in the myObjects namespace
function getName(){
  return myObjects.Name;
}

//now we can use it like:
  setName("kevin");
  var x = getName();
  var y = x;
  console.log(y)  //"kevin"
  var z = "y";
  console.log(z); //"y"
  console.log(eval(z)); //"kevin"

通过这种类似的方式,我们可以声明和使用多个变量。虽然这将增加代码行,但代码将更健壮,更不容易出错。

1赞 unbreak 9/16/2020 #17

这将完全执行您在 php 中所做的操作:

var a = 1;
var b = 2;
var ccc = 3;
var name = 'a';
console.log( window[name] ); // 1

评论

0赞 Alexander Shestakov 2/24/2021
使用全局范围 - 恕我直言,这是个坏主意
1赞 M Komaei 7/13/2022 #18

最简单的解决方案:创建一个对象数组,每个对象都有两个字段(variableName,variableValue)

let allVariables = [];

for (let i = 0; i < 5; i++)
    allVariables.push({ variableName: 'variable' + i, variableValue: i * 10 });

for (let i = 0; i < allVariables.length; i++)
    console.log(allVariables[i].variableName + ' is ' + allVariables[i].variableValue);

输出:

variable0 is 0
variable1 is 10
variable2 is 20
variable3 is 30
variable4 is 40

console.log(allVariables) json :

 [
    {
        "variableName": "variable0",
        "variableValue": 0
    },
    {
        "variableName": "variable1",
        "variableValue": 10
    },
    {
        "variableName": "variable2",
        "variableValue": 20
    },
    {
        "variableName": "variable3",
        "variableValue": 30
    },
    {
        "variableName": "variable4",
        "variableValue": 40
    }
]