0

我听到了很多关于 eval() 的不同意见,并且有点不确定在这种情况下使用 eval() 是否可以:

假设我有一个这样的对象:

var bla = {
blubb: function (callback) {
       //GET some stuff via ajax
       //call the callback
    }
}

还有这样的字符串:

 var someString = "bla.blubb";

评估字符串以调用函数(和回调)是邪恶的吗?

var callMe = eval(someString)
callMe(function(){
   alert('yay')!
});
4

4 回答 4

5

我听到了很多关于 eval() 的不同意见

eval一般不是邪恶的,有它的应用程序。

不确定在这种情况下是否可以使用 eval()

不,这样不行。使用简单的括号符号 member operator有一个更好的解决方案。由于每天都会在 SO 上询问这个问题,我可以在这里列出数百个骗子(只是谷歌的前几个结果):

于 2013-01-18T10:34:40.897 回答
1

让我们假设您的整个设计并不完全是邪恶的(但有一点)。

这意味着您限制并指定您在someString. 例如,它可以是一个对象及其函数的路径,您可以在没有任何参数的情况下调用它(这使得它的危险性降低了很多),并且在上下文中是全局对象。

然后很容易解析字符串并调用没有eval. 这样会更安全。例如 :

window.a = {b:{c:function(){console.log('here')}}};
var someString = "a.b.c";

var path = someString.split('.');
var f = window;
for (var i=0; i<path.length; i++) f = f[path[i]];
f.call(null);

一个改进是修复根对象(而不是窗口)以避免任何类型的调用。

于 2013-01-18T10:21:07.627 回答
0

这又是邪恶的,因为它很难调试。更好的方法是使用类似的东西:

function getValue(namespace, parent) {
    var parts = namespace.split('.'),
        current = parent || window;
    for (var i = 0; i < parts.length; i += 1) {
        if (current[parts[i]]) {
            current = current[parts[i]];
        } else {
          if (i >= parts.length - 1)
            return undefined;
        }
    }
    return current;
}
var foo = {
    bar: {
        baz: function () { alert('baz'); }
    }
};
var f = getValue('foo.bar.baz'); //true
if (typeof f === 'function') {
    f();
}

代码不止一个eval('foo.bar.baz'),但您可以弄清楚实际发生了什么,甚至可以使用断点对其进行调试。

如果我们在这里谈论性能,那么这里有几个 jsperf 示例:

  1. http://jsperf.com/eval-vs-loop
  2. http://jsperf.com/eval-vs-loop/2
于 2013-01-18T10:20:58.727 回答
0

如果你知道你的对象会是什么样子,不要忘记你可以在 javascript 中使用“安全评估”。

在范围内:

this.foo = { bar:function(){return "baz"}};

// some code.
var obj = "foo";
var param = "bar";

this[obj][param](); // same as this.foo.bar();

除非您正在处理一些特定的事情(例如模板),否则您不需要使用 eval 来调用对象。

于 2013-01-18T10:28:13.483 回答