由于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相同的问题。但为什么" varFunc"如果" globalVarFunc"不起作用。呢?
编辑:我希望在列表中运行" varFunc"。
答案 0 :(得分:1)
我认为你缺少的是两个概念之间的关系:
我们举一个简单的例子:
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()
或不是undefined
,您无法在该范围内调用仅Lion
的内容;这是不合逻辑的。
有点像两个表演戒指和一个带有狮子的神奇笼子。当您将ring(Lion)
发送到另一个响铃ring('Lion')
时,您已经指着笼子并说要获得狮子的副本并将其放入该戒指 。
当您说Lion
时,您已告知另一个 Lion ,但未定义Lion
。所以那个戒指正在跑来跑去说狮子!狮子!但是没有Lion
,只有一个字。 undefined
是{{1}},因此您不会获得演出,而是会得到一个滑稽而又错误的结果。人们可能会想要他们的钱。
这就是为什么你要做的事情不会起作用。
*许多语言允许您通过引用传递,但Javascript不允许。