【问题标题】:Trying to avoid eval getting array element from window object试图避免 eval 从窗口对象获取数组元素
【发布时间】:2011-12-02 00:44:17
【问题描述】:

我有一个想要访问全局变量的函数,该变量的名称作为字符串参数到达。这是现在的样子,使用 eval:

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

我以为我只需要使用 window[] 语法就可以了:

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

如果我创建一个 var 并像这样调用它,它会按预期写入 ABC:

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

如果我要访问的 var 是一个数组元素,它就不起作用:

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

显然,这实际上是在执行 window[def[0]] ,它正确地给出了 undefined (因为没有名为 DEF 的变量)。我真正想要发生的是它执行 window["def"][0].

我知道实现这一点的唯一方法是使用“[”作为分隔符对 whichone 参数进行拆分,然后使用拆分 [0] 作为窗口索引,并在拆分 [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] );
  }
}

我是否忽略了一些明显的东西?我宁愿保留 eval 而不是必须做所有这些。

【问题讨论】:

  • 有没有办法让值以更好的方式传递?
  • 这是一个实验还是您正在尝试将此技术用于生产用途?
  • 我正在使用一个库(像 jquery 但不是 jquery),它恰好以这种方式向我传递了 var 的名称。遗憾的是,我无法更改收到的内容,只能更改我的使用方式。

标签: javascript eval


【解决方案1】:

如果您不喜欢在代码中使用 eval,您可以随时这样做:

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

【讨论】:

  • 我可能错了,但这不是在幕后使用 eval 吗?很难想象没有它会如何执行。就像 document.write(23) 使用 .toString() 一样,即使你在那里看不到它。
  • 嗯,不是真的。那里有一些帖子解释了 eval 和 Function 之间的区别。顺便说一句,23 没有要调用的 toString 方法。如果您不信任我,请尝试var x = 23; x.toString = function () { return "69"; }; document.write(x);。现在将第一条语句替换为var x = Object(23);,您将看到不同之处。
  • 我喜欢。我采用了这种方法:)
【解决方案2】:

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

【讨论】:

  • 这是真的。不过我无法控制设计。
【解决方案3】:

事实上,您在字符串中有一段 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/

【讨论】:

  • 然后,您必须自己解析或使用 eval() - 您的选择。只要这不是最终用户提供的字符串,我认为仅使用 eval() 没有问题。
  • 这也是我自己得出的结论,要么使用 eval 要么用半打代码膨胀它。不过我想我会来这里看看是否有一个我不知道的聪明的解决方案。
【解决方案4】:

去掉括号并用点表示法调用项目会更简单

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

【讨论】:

  • 只是稍微简单一点,它只是意味着我没有尾随 ],无论如何 parseInt 都会忽略它。此外,我无法控制调用格式,否则我会完全重新设计它并让它传递对象本身而不是字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-14
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
相关资源
最近更新 更多