0

我有一个方法的名称作为 javascript 变量中的字符串,我想得到它调用变量的结果:

var myMethod = "methodToBeCalled";
var result;
eval("result = "+myMethod+"();")

这有效,没有问题。但是这个代码对于 Google Closure Compiler 是不可接受的。如何修改它以使用它?谢谢!

编辑:

当方法的名称在某个对象内部时,建议的解决方案似乎不起作用,例如:

var myFunction = function () { return "foo!" }
var myObject = {
    itsMethod: function() { return "foo!" }
};
...
var fstMethodToCall = "myFunction"
var sndMethodToCall = "myObject.itsMethod";
...
window[fstMethodToCall](); // foo!
window[sndMethodToCall](); // undefined
4

3 回答 3

2

假设您不在某种嵌套范围内,请尝试:

var result = window['methodToBeCalled']();

或者

var myMethod = 'methodToBeCalled';
var result = window[myMethod]();

要根据字符串规范执行任意深度的任意函数,而不执行 eval:

var SomeObject = {
    level1: {
        level2: {
            someFunc: function () {
                console.log('hello');
            }
        }
    }
};

var target = 'SomeObject.level1.level2.someFunc';

var obj;
var split = target.split('.');
for (var i = 0; i < split.length; i++) {
    obj = (obj || window)[split[i]];
}

obj();
于 2012-04-27T17:31:15.903 回答
2

您可以使用索引器表示法:

result = window[myMethod]();
于 2012-04-27T17:31:31.953 回答
1

闭包编译器不禁止'eval',如果你觉得方便,你可以继续使用它,但你必须明白编译器不会试图理解你的eval语句中发生的事情,并假设你的eval是“安全的”:

function f(x, y) {
  alert(eval("y")); // fails: hidden reference to "y"
  alert(eval('"'+x+'"'));   // might be valid
}
f('me', 'you');

当编译器优化此函数时,它会尝试删除“y”并重命名剩余参数。这将是第一个失败的评估,因为“y”不再存在。第二个评估将正确显示警报“我”。

因此,通过 SIMPLE 优化,您可以使用 eval 来引用全局变量和对象属性,因为它们不会被重命名或删除(但不是本地的)。

使用高级优化,它有点棘手,因为编译器试图删除和重命名全局变量和局部变量。因此,您需要导出需要保留的值。如果您使用字符串尝试通过其他方式引用名称,这也是正确的:

var methodName = "myMethod";
(window[methodName])()

或者

var methodName = "myMethod";
eval(methodName+"()")

编译器根本不会尝试确定“methodName”是否是对函数的引用。这是一个高级模式导出的简单示例:

window['myMethod'] = myMethod;

该赋值做了两件事:如果 myMethod 函数将被删除,它会保留它,并且通过使用字符串将其分配给属性来为其提供固定名称。如果确实需要引用本地值,则需要稍微复杂一点并使用 Function 构造函数。我的第一个示例中的“f”定义,可以评估本地人:

var f = new Function("x", "y", "alert(eval('y')); alert(eval('\"' + x + '\"'));");

您可能会发现此页面很有用:

https://developers.google.com/closure/compiler/docs/limitations

于 2012-04-28T15:34:27.747 回答