在JavaScript中将字符串转换为变量名

325

我已经寻找解决方案,但是没有找到可行的。

我有一个叫做onlyVideo的变量。

"onlyVideo" 这个字符串被传递到一个函数中。我想在函数内部将变量 onlyVideo 设置为某个值。我该怎么做?

(有许多变量可以调用到函数中,因此我需要它能够动态工作,而不是硬编码的if语句。)

编辑:也许有更好的方法来实现你尝试做的事情。我在学习JavaScript初期问过这个问题。了解一下JavaScript对象是如何工作的吧。

一个简单的介绍:

// create JavaScript object
var obj = { "key1": 1 };

// assign - set "key2" to 2
obj.key2 = 2;

// read values
obj.key1 === 1;
obj.key2 === 2;

// read values with a string, same result as above
// but works with special characters and spaces
// and of course variables
obj["key1"] === 1;
obj["key2"] === 2;

// read with a variable
var key1Str = "key1";
obj[key1Str] === 1;

6
你是用这个来做什么的?你确定一定要将它设置为普通局部变量,而不是使用对象(哈希)吗? - Dogbert
嗯...我仍然不太明白为什么在有数组的世界里你想要这样做。无论如何,一些你的代码和解释会非常有帮助。 - Kevin Chavez
我认为我们需要更多关于你的最终目标的细节。 - mcgrailm
12个回答

344
如果它是全局变量,那么window[variableName]或者在你的情况下window["onlyVideo"]就可以解决问题。

50
即使不是全局的,您也可以通过 scope[property] 或者甚至 this[property] 进行访问。 - Wojciech Bednarski
13
不要混淆作用域和上下文。在JavaScript中,this是上下文,它所指向的取决于函数的调用方式。50%的时间,除非启用严格模式,否则thiswindow,并且在这种情况下,this将变为未定义并抛出错误。作用域完全不同,并且不是对象(除了全局作用域,它由window对象所反映)。 - slebetman
3
WebWorkers中不起作用(在那里,self指的是全局作用域,就像在浏览器中一样,它等同于window),在Node.js中使用global变量。并且它不适用于局部作用域,比如函数体。 - Tomáš Zato
1
有没有办法使用这种方法定义一个const - toing_toing
2
如果使用let和const创建变量,它将不会成为全局作用域的一部分。 - Sameer Reza Khan
如果正在测试全局变量,那么应该使用globalThis而不是其他(更通用的)方法吗? - polendina

221

Javascript有一个eval()函数可以用于这种情况:

function (varString) {
  var myVar = eval(varString);
  // .....
}

编辑:抱歉,我想我太快地浏览了问题。 这只会为您获取变量,要设置它,您需要

function SetTo5(varString) {
  var newValue = 5;
  eval(varString + " = " + newValue);
}

或者如果使用字符串:

function SetToString(varString) {
  var newValue = "string";
  eval(varString + " = " + "'" + newValue + "'");
}

但我想象中有一种更合适的方法来完成你要做的事情吧?我认为除非有充分的理由,否则不应使用eval()。eval()


4
我会选择这个选项,而不是使用窗口(它有一些注意事项)。 - ingo
13
为什么一个eval()的答案被投票删除了,而这个答案却被赞同了? - BoltClock
5
你应该对参数进行正则表达式测试,以确保它是一个有效的名称。如果没有先对参数进行检查就对其进行评估,那么这种做法非常不安全。 - Šime Vidas
21
这是对这个问题唯一现实的答案。只是因为它涉及到“邪恶”的 eval,并不意味着它不真实。JavaScript没有变量变量(例如 PHP 中的 $$varname),所以这确实是唯一的答案。使用 window[varname] 会引入全局变量的副作用,这可能不是想要的。@Shaz,我认为你没有给现代 JS 解释器足够的信任。它们非常快,并且解析和执行一个简单的一行赋值操作不会使 CPU 使用率飙升,只要它不是在1毫秒计时器或紧密循环中进行。 - MooGoo
2
那些热爱编程的人在意这个。而那些只关心时间和金钱的人则不会。 - Jimbo
显示剩余7条评论

54

就 eval vs. 全局变量解决方案而言...

我认为每种方法都有优点,但这实际上是一个错误的二分法。 如果您对全局命名空间很担心,只需创建一个临时命名空间并使用相同的技术即可。

var tempNamespace = {};
var myString = "myVarProperty";

tempNamespace[myString] = 5;

我相信你可以将其作为tempNamespace.myVarProperty(现在是5)访问,避免使用window进行存储。(该字符串也可以直接放入括号中)


稍微重构一下你的代码,使其内联var tempNamespace = {["myVarProperty"]: "绝对只有视频"}; - Tioma
1
这是一个非常好的解决方案 - 似乎应该尽量避免使用eval(),这里提供了非常优雅的解决方法。 - skwidbreth
从集合document.body.getElementsByTagName('*')开始,很容易找到所有具有'id'属性的元素,并为每个元素对象值创建一个全局对象'id'的变量。然后,您可以在JavaScript中引用<div id=container>作为'id.container'。如此简单! - David Spector

22
var myString = "echoHello";

window[myString] = function() {
    alert("Hello!");
}

echoHello();

拒绝使用 危险的 eval。示例在这里:https://jsfiddle.net/Shaz/WmA8t/


4
如果您将此工作应用于本地范围,我将取消投票反对。 - Tomáš Zato
@TomášZato function aScope() { this[myString] = function() { alert("Hello!"); };}; - rrw
@richmondwang this 不是指向本地作用域,而是指向函数在调用时绑定的对象。 - Tomáš Zato

10

您可以这样做

var name = "foo";
var value = "Hello foos";
eval("var "+name+" = '"+value+"';");
alert(foo);


9
你可以将window对象作为关联数组访问并进行设置。
window["onlyVideo"] = "TEST";
document.write(onlyVideo);

7

如果你想访问对象的属性,你需要从window的范围开始,并沿着对象的每个属性一直找到你想要的那一个。假设a.b.c已经在脚本的其他地方定义好了,你可以使用以下方法:

var values = window;
var str = 'a.b.c'.values.split('.');

for(var i=0; i < str.length; i++)
    values = values[str[i]];

这将适用于获取任何对象的属性,无论它有多深。

你的示例很棒。我注意到如果我使用name作为变量名,你的示例会失败,但是其他变量名却可以成功。这可能与Window对象已经有一个名为 name的变量有关。此外,包括.value方法也导致了故障。我正在寻找解释深度嵌套对象变量的能力,而你的方法指明了一个好的方向。谢谢。 - Theo
没问题。答案更多是为了演示概念,而不是复制/粘贴答案(就像这里大多数答案一样,我认为)。 - user1846065
1
当你可以花时间改进回答而不是修复它们时,SO的回复会更好。;-) - Theo
无法工作:未捕获的类型错误:无法读取未定义的'split'属性 - Roberto14

7

如果变量在全局作用域中定义,则window ['variableName']方法才有效。 正确答案是“重构”。 如果您可以提供“对象”上下文,则可能存在一种通用解决方案,但是有些变量基于变量的作用域无法解析任何全局函数。

(function(){
    var findMe = 'no way';
})();

0

可以这样实现

(function(X, Y) {
  
  // X is the local name of the 'class'
  // Doo is default value if param X is empty
  var X = (typeof X == 'string') ? X: 'Doo';
  var Y = (typeof Y == 'string') ? Y: 'doo';
  
  // this refers to the local X defined above
  this[X] = function(doo) {
    // object variable
    this.doo = doo || 'doo it';
  }
  // prototypal inheritance for methods
  // defined by another
  this[X].prototype[Y] = function() {
    return this.doo || 'doo';
  };
  
  // make X global
  window[X] = this[X];
}('Dooa', 'dooa')); // give the names here

// test
doo = new Dooa('abc');
doo2 = new Dooa('def');
console.log(doo.dooa());
console.log(doo2.dooa());


0
以下代码使得在JavaScript中可以轻松地引用每个DIV和其他HTML元素。这段代码应该在“”标签之前包含,以便所有的HTML元素都已经被看到。它应该跟随着你的JavaScript代码。
// For each element with an id (example: 'MyDIV') in the body, create a variable
// for easy reference. An example is below.
var D=document;
var id={}; // All ID elements
var els=document.body.getElementsByTagName('*');
for (var i = 0; i < els.length; i++)
    {
    thisid = els[i].id;
    if (!thisid)
        continue;
    val=D.getElementById(thisid);
    id[thisid]=val;
    }

// Usage:
id.MyDIV.innerHTML="hello";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接