2011-12-02 52 views
0

我有一个函数想要访问一个全局变量,其名称作为字符串参数到达。这是现在的样子,使用eval:试图避免eval从窗口对象获取数组元素

function echoVar(whichone){ 
    document.write(eval(whichone)); 
} 

我想我只是用窗口[]语法和有这样的:

function echoVar(whichone) { 
    document.write(window[whichone]); 
} 

如果我创建一个变种,并调用它像这样,它的文档写ABC预期:

var abc = "ABC"; 
echoVar("abc"); 

如果我要访问的变种是虽然一个数组元素,这是行不通的:

var def = ["DEF"]; 
echoVar("def[0]"); //fails with undefined 

很明显,这实际上是执行window [def [0]],它正确地给出了未定义的(因为没有称为DEF的变量)。我真正想要发生的是它执行窗口[“def”] [0]。

我知道要做到这一点的唯一方法就是用“[”作为分隔符,然后使用split [0]作为窗口索引和split [1]上的parseInt来分割哪个参数得到的索引,像这样:

function echoVar(whichone){ 
    if(whichone.indexOf("[")==-1){ 
    document.write(window[whichone]); 
    } 
    else{ 
    var s = whichone.split("["); 
    var nam = s[0]; 
    var idx = parseInt(s[1]); 
    document.write(window[nam][idx]); 
    } 
} 

我可以忽略一些明显的东西吗?我宁愿保持评估,也不愿意做所有这些。

+0

难道没有办法让价值以更好的方式传递吗? –

+0

这是一个实验还是您正在尝试将此技术用于生产用途? –

+0

我正在使用一个库(如jquery,但不是jQuery),它恰好以这种方式传递了var的名称。可悲的是我不能改变我收到的东西,只是我如何使用它。 – Dee2000

回答

1

如果你不喜欢在你的代码使用eval,你总是可以做到这一点:

function echoVar(whichone) { 
    document.write(Function("return " + whichone)()); 
} 
+0

我可能错了,但不是在幕后使用eval吗?很难想象没有它会如何执行。而是像document.write(23)使用.toString(),即使你看不到它。 – Dee2000

+0

呃,不是真的。有帖子解释了eval和Function之间的区别。顺便说一下,23没有'toString'方法来调用。如果你不信任我,试试'var x = 23; x.toString = function(){return“69”; };文件撰写(X);'。现在用'var x = Object(23);'替换第一条语句,你会看到区别。 – ft1

+0

我喜欢它。我采用了这种方法:) – Dee2000

0

除非这是一些生病的实验,否则不应该编写看起来像这样的Javascript代码。这很糟糕;你需要重新考虑你的设计。我知道这不是你要找的,但它是正确的答案。

+0

这是真的。虽然我无法控制设计。 – Dee2000

0

事实是你已经有了一块javscript表达的一个字符串,所以你要么必须自己解析它或使用eval,除非你改变它通过这样的方式来解析它给你:

function echoVar(a,b) { 
    var x = window[a]; 
    if (b) { 
     x = x[b]; 
    } 
    document.write(x); 
} 

而且,那么你可以通过不同的像这样:

var def = ["DEF"]; 
echoVar("def", 0); // def[0] 

你甚至可以使这一支持多种尺寸,如果你需要的。

function echoVar(a) { 
    var x = window[a]; 
    for (var i = 1; i < arguments.length; i++) { 
     x = x[arguments[i]]; 
    } 
    document.write(x); 
} 

var def = {myObject: {length: 3}} 
echoVar("def", "myObject", "length"); // def["myObject"]["length"] or def.myObject.length 

你可以看到它在这里工作:http://jsfiddle.net/jfriend00/dANwq/

+0

可悲的是我不能控制调用格式。 – Dee2000

+0

然后,您必须自己解析它或使用eval() - 您的选择。只要这不是最终用户提供的字符串,我看不到只使用'eval()'的问题。 – jfriend00

+0

这就是我自己也得出的结论,无论是使用eval还是使用六行代码膨胀它。我想我会来这里,看看是否有一个我不知道的聪明解决方案。 – Dee2000

0

它会更简单失去支架和用点分数表示该物品

function reval(s, O){ 
    s= String(s); 
    O= O || window; 
    var N= s.split("."); 
    while(O && N.length) O= O[N.shift()]; 
    return O || s; 
} 

window.def= ['definition']; 
alert(reval('def.0')) 

/* returned value: (String) 
definition 
*/ 
+0

只是稍微简单一点,它只是表示我没有结尾],而parseInt无论如何都忽略它。另外,我没有控制调用格式,否则我会重新设计它,并且使它传递对象本身而不是字符串。 – Dee2000