Javascript 呼叫“a”;“本地”;函数的字符串名不带eval?

Javascript 呼叫“a”;“本地”;函数的字符串名不带eval?,javascript,function,eval,Javascript,Function,Eval,由于几个原因,eval不再使用,因此我正在处理调用函数时遇到的一些问题。所以我做了一个“函数调用者”来代替eval。首先:我是不是把安全性、速度和调试困难等评估问题带回来了?以下是测试代码: function globalFunc(p){ console.log("Run globalFunc: "+p); } var globalVarFunc = function(p){ console.log("Run globalVarFunc: "+p); } function ini

由于几个原因,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();

调用
run()
时,它有自己的作用域,这是它自身的局部作用域。其中声明的变量和函数有自己的引用,这些引用仅在
函数run(){}
中可见

当您通过
run(test)
时,您通过查找变量的引用来传递变量的值,这样就可以将其理解为一个副本;如您所见,您不会影响最初引用的变量,而是更改它的本地实例*

这很重要的原因是,如果在新范围中没有与该引用相关联的值(在您的例子中是函数值),那么您所拥有的只是一个与其原始值无关的字符串
eval();这是不合逻辑的

这有点像有两个表演戒指和一个魔法笼子,笼子里有狮子。当你把一只
狮子
送到另一只戒指上,
戒指(狮子)
,你就指着笼子说,拿一只狮子的副本,把它放在那只戒指上

当你说
ring('Lion')
时,你已经告诉了另一只ring Lion,但是没有定义
Lion
。所以那个戒指在说狮子!狮子!但是没有狮子,只有一个字
Lion
未定义的
,因此你不会得到一场演出,而是得到一个滑稽但错误的结果。人们可能会想要回他们的钱

这就是为什么你想做的事行不通



*许多语言允许您通过引用传递,但Javascript不允许。

您想要实现的到底是什么?而且,“varFunc”确实有效-它就在您的调试输出中@尖刻-我认为这是OP询问的文字
“varFunc”
。换句话说,OP不理解传递引用和作用域。如果您需要,那么您应该使用普通的
eval
,而不是尝试模拟它的一些粗糙的解决方法。然而,几乎总是有更好的解决方案。我写了上面问题的主要目的@贾雷德法里什:你说得对!Bergi:我认为eval将被弃用,将完全停止工作。JSFIDLE关闭了,我将在这里做更多的测试,我希望一次性理解这个概念!虽然JSFIDLE没有回来,但我测试了您令人兴奋的代码。我知道,在我的代码中,globalFunc已经在funcCaller中定义,因为两者都在根中。狮子跳进笼子里,弄糊涂了我的头脑。更进一步说,我认为向调用者传递字符串和函数可能有区别:是在框架外部还是内部运行?这可能超出了问题的范围,你的电话。答案可能是,有时字符串不起作用,这不是代码问题,而是范围问题。谢谢你!答案是,字符串必须引用一些计算结果为指向函数的内容(框架表示在内存中存储函数的框,引用是它的地址),才能调用函数。事实上,笼子里有一头狮子。调用全局函数时,实际上是在调用隐式的
窗口['functionName']()
(或
window.functionName()
)。换句话说,您引用的对象属性指向内存中计算结果为该字符串的函数。有关其他拍摄,请参见: