由于出于多种原因不再使用 eval,我正在处理调用函数的一些问题。所以我正在制作一个“函数调用者”来代替 eval。首先:我是否带回了安全性、速度和调试困难等评估问题?测试代码如下:
function globalFunc(p){
console.log("Run globalFunc: "+p);
}
var globalVarFunc = function(p){
console.log("Run globalVarFunc: "+p);
}
function ini(){
var varFunc = function(p){
console.log("Run varFunc: "+p);
}
//
funcCaller(function(p){ console.log("Run anonymous function: "+p); }, "anonymous");
funcCaller('function(p){ console.log("Run anonymous function: "+p); }', "anonymous");
funcCaller(globalFunc, "global function");
funcCaller("globalFunc", "global string");
funcCaller(globalVarFunc, "globalVarFunc function");
funcCaller("globalVarFunc", "globalVarFunc string");
funcCaller(localFunc, "local function");
funcCaller("localFunc", "local string");
funcCaller(varFunc, "local var function");
funcCaller("varFunc", "local var string");
//
function localFunc(p){
console.log("Run localFunc: "+p);
}
}
function funcCaller(func, p){
if(typeof(func)=="string"){
p += " as string";
try { window[func](p); } catch(e) {
console.log("Catch window error trying "+p) ;
try { this[func](p); } catch(e) { console.log("Catch this error trying "+p) }
}
} else if(typeof(func)=="function"){
p += " as function";
try { func(p); } catch(e) { console.log("Catch error trying "+p) }
} else {
console.log("Unknown situation: "+typeof(func)+" trying "+p);
}
}
Safari 5.1 的日志结果:
Run anonymous function: anonymous as function
Catch window error trying anonymous as string
Catch this error trying anonymous as string
Run globalFunc: global function as function
Run globalFunc: global string as string
Run globalVarFunc: globalVarFunc function as function
Run globalVarFunc: globalVarFunc string as string
Run localFunc: local function as function
Catch window error trying local string as string
Catch this error trying local string as string
Run varFunc: local var function as function
Catch window error trying local var string as string
Catch this error trying local var string as string
也许不建议将匿名函数作为字符串运行,与 eval 存在同样的问题。但是,如果“globalVarFunc”可以工作,为什么“varFunc”不起作用呢?
编辑:我希望在列表中运行“varFunc”。
最佳答案
我认为您缺少的是两个概念之间的关系:
- 通过引用传递
- 范围
让我们举一个简单的例子:
function check(arg) {
try {
var func = new Function('return ' + arg + '()');
console.log(typeof arg, this);
console.log(func);
console.log(func());
} catch (e) {
console.log(e);
}
}
function run() {
function test() {
console.log('Local test() run.');
}
check(test);
check('test');
}
var r = new run();
http://jsfiddle.net/userdude/7Lz15qou/
当run()
被调用时,它内部有它自己的范围,它是它自己的本地范围。其中声明的变量和函数都有自己的引用,这些引用只能在function run(){}
中看到。
当您传递run(test)
时,您通过查找变量的引用来传递变量的值,这使得它可以被理解为副本;如您所见here ,您不会影响最初引用的变量,而是更改它的本地实例*。
这很重要的原因是,如果没有与新作用域中的引用关联的值(在您的情况下是函数值),您所拥有的就是与其原始值无关的字符串。无论是否使用 eval(),您都不能调用该范围内未定义的内容;这是不合逻辑的。
这有点像有两个表演环和一个神奇的笼子,其中一个环里有狮子。当您将Lion
发送到另一个环ring(Lion)
时,您指着笼子并说获取狮子的副本并将其放入在那枚戒指中。
当您说ring('Lion')
时,您已经告诉另一个环Lion,但没有定义Lion
。所以那个戒指到处跑,上面写着狮子!狮子!但是没有狮子
,只有一个词。 Lion
是未定义
,因此您得到的不是表演,而是滑稽但错误的结果。人们可能会想要回他们的钱。
这就是为什么您尝试做的事情不起作用。
<小时/>* 许多语言允许通过引用传递,但 Javascript 不允许。
关于javascript - 通过字符串名称调用 "local"函数而不使用 eval?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25219442/