ChatGPT解决这个技术问题 Extra ChatGPT

在 JavaScript 中使用动态变量名

在 PHP 中,你可以做如下惊人/可怕的事情:

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

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

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

这回答了你的问题了吗? "Variable" variables in Javascript?。那里接受的答案比这里的要好,因为它展示了如何去做,而且正确地警告说,几乎总是有更好的方法来做你想做的任何事情。请参阅关于元的 XY problem

u
uingtea

由于 ECMA-/Javascript 都是关于 ObjectsContexts(它们也是某种对象),因此每个变量都存储在称为 Variable- 的此类中(或者在函数的情况下, 激活对象)。

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

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

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

这些可以通过使用“点”或“括号”符号来访问:

var name = window.a;

或者

var name = window['a'];

这仅适用于此特定实例中的全局对象,因为 全局对象变量对象 就是 window 对象本身。在函数的上下文中,您无法直接访问激活对象。例如:

函数 foobar() { this.a = 1;这个.b = 2;变量名称 = 窗口 ['a']; // === 未定义 console.log(name);名称 = 这个['a']; // === 1 console.log(name); } 新的 foobar();

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

var a = 1,
    b = 2;

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


另一个很酷的事情是,通过这种方式,您可以为任何全局级别的函数添加回调(开始/结束)。
但是如果我的动态变量在函数中是局部的呢?例如:函数 boink() { var a = 1; // 这不起作用 var dynamic = this['a']; // 这也不行 var dynamic = ['a']; }
@Kokodoko——因为这不是“上下文”或对函数执行上下文的引用(无法引用执行上下文,ECMA-262 禁止这样做)。 this 由函数的调用方式(或绑定)设置,它只是一个对象,与可访问的执行上下文无关。
如果您需要访问嵌套属性,请查看 stackoverflow.com/questions/4244896/…
用括号符号为我指明了正确的方向。只考虑点符号。
u
uingtea

eval 是一种选择。

变量 a = 1;变量名称 = 'a'; document.write(eval(name)); // 1

警告:请注意,如果您不知道自己在做什么,不建议使用 eval() 函数,因为它会带来多个安全问题。除非绝对必要,否则请使用其他东西。有关详细信息,请参阅 the MDN page for eval


不,它不应该因为 eval 是邪恶的。永远不要使用评估!
@EasyBB - 如果您要说永远不要使用某些东西,我无助于解释原因。我有一种情况,除了 eval() 之外,我想不出任何其他方法来完成我正在做的事情
Eval 对最终用户的攻击构成了风险,我们认为它在技术上并不是邪恶的,而是在丢失的案例中被误解和滥用。我已经看到 php 响应在其中包含文字变量,然后使用 eval 运行它。尽管在这种情况下不应该使用它,因为有更好的方法。根本不应该使用这个问题 eval ,因为总体上有更好的方法,我相信我们很多人都知道这一点。
通过 javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval ---“让我们考虑最常反对使用 eval 的参数:1)它需要编译,因此速度很慢 2)如果恶意脚本进入 eval 参数怎么办?3)看起来很难看 4 ) 它继承执行上下文和调用它的范围的 this 绑定”
以下是使用 eval 创建动态变量的方法:stackoverflow.com/a/13291766/5528600
d
de-russification

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

window['myVar']

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


不用说,这个比 eval() 更安全。
window 看起来像 state。这真的很有帮助。
但是当我想使用本地变量时呢?
@BuSaeed 不确定我是否理解,如果变量已经是本地范围,你不能直接按名称引用它吗?您可能应该问一个新问题,因为这是一个具有不同含义的旧问题。
s
shkschneider

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

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

“在我们使用 this 的函数中” - 如果您想以这种方式访问 全局 变量,最好明确并使用 window 对象,而不是 thisthis 不明确。
但是在函数内部您不能使用 this 或其他任何东西来访问示例中的变量 type,如果您将其名称包含在另一个变量中:function test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type') 将显示 {4 },而不是 something else。这就是“复杂答案”所解释的。
这不起作用。如果您将 undefined 放入函数并使用对象(使用 new 运算符或使用点符号)调用它,它会将 undefined 输出到警报框。
在 Express.js 路由中运行良好
感谢@Terry,这在 Vue 中完美运行。当您声明了多个数据属性,并且您想要一个方法来决定要定位哪个数据属性时,您只需像这样传递属性名称:changeProperty(propertyName) { this[propertyName] = 1; } changeProperty("bar") changeProperty("baz")
A
Azodium

这是一个例子:

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


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

尝试这个...


D
David Newcomb

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

var someJsonObj = {};在一个循环中...... for(var i=0; i<=3; i++) { someJsonObj[i] = []; },但我可以是任何东西。如此动态生成的变量,都位于 someJsonObj 中以便于参考。
B
Brent Barbata

如果你不想使用像 window 或 global (node) 这样的全局对象,你可以尝试这样的事情:

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

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

p
pery mimon

2019

TL;博士

eval 运算符可以在它调用的上下文中运行字符串表达式并从该上下文返回变量;

文字对象理论上可以通过 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 引擎无法优化该方法。
很棒的解决方案
“默认”是 JavaScript 中的保留字。您不应将其用作变量名
T
Talha

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

var forms = {}

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

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

谢谢...它完全救了我! this.$refs['listView' + index].nativeView.animate({..}) 我需要像 this.$refs.listView1 listView2 这样的 refs 内的变量等等......
J
JeanAlesi

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

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

为什么需要 import/export 来执行此操作?为什么不简单地创建一个对象并访问它的属性呢?此外,不可能导出动态名称,除非您将对象导出为默认值...
S
Steve Jiang

使用对象也很棒。

var a=123
var b=234
var temp = {"a":a,"b":b}
console.log(temp["a"],temp["b"]);

e
enxaneta

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

在 ES6 中使用 let 不起作用

/*这不起作用*/ let t = "skyBlue", m = "gold", b = "tomato";让颜色 = 窗口 [“b”];控制台.log(颜色);

但是使用 var 工作

/*这是有效的*/ var t = "skyBlue", m = "gold", b = "tomato";让颜色 = 窗口 [“b”];控制台.log(颜色);

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


同样适用于 const
真的。但是您可以使用变量创建一个对象并从那里选择变量:const vars = { t, m, b }; console.log(vars['b'])。否则 eval 也可以。
@FabianvonEllerts 你评论的目的是什么?此答案仅旨在解决块级范围(let & const)和全局(window)范围(var & function)之间的区别。您的评论与此无关,而是作为单独的答案。
u
unbreak

这将完全按照您在 php 中所做的操作:

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

使用全局范围 - 是个坏主意,恕我直言
A
Alfgaar

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

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 中实现的那样。


注意: const 是 ES6 中的关键字
...在此之前是一个未来的保留字。
eval 运算符
A
Axel Heider

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)

小改进,最好使用 var node_head = document.getElementsByTagName("head")[0] 而不是 ID,因为没有人给 <head> 提供 id="head" :-)
我愿意 :) 但是谢谢,现在我终于可以删除这个 `id="head" 东西了
这似乎是创建全局变量的一种过于复杂的方法?! (......这如何回答这个问题?)
天才:) eval 是解决方案。即使您的代码不起作用
H
HeadJk

这是纯 javascript 解决方案,它不依赖于运行时环境的全局 this。使用对象解构很容易实现。

const dynamicVar = (nameValue, value) => {
    const dynamicVarObj = {
        [nameValue]: value
    }
    return dynamicVarObj;
}

const nameToUse = "myVar";
const value = 55;

const { myVar } = dynamicVar(nameToUse, value);

console.log(myVar); // prints 55

M
M Komaei

最简单的解决方案:创建一个对象数组,每个对象都有两个字段(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
    }
]

R
Rishu Ranjan

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

请参见下面的代码片段:

//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"

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