使用eval将字符串转换为函数是不是很邪恶?

时间:2013-01-18 10:13:50

标签: javascript

我听过很多关于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')!
});

3 个答案:

答案 0 :(得分: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);

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

答案 1 :(得分: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

答案 2 :(得分: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来调用对象。