打电话给本地"函数字符串名称没有eval?

时间:2014-08-09 14:14:59

标签: javascript function eval

由于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"。

1 个答案:

答案 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不允许。