我听过很多关于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')!
});
答案 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例子:
答案 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来调用对象。