这有效:
var i = 'foo';
eval('function '+i+'(param) { this.param = param; return this; }');
console.log(foo); // [Function: foo]
这不会:
['bar', 'quux'].forEach(function(i) {
eval('function '+i+'(param) { this.param = param; return this; }');
});
console.log(bar); // ReferenceError: bar is not defined
显然,forEach
功能或其从属范围混淆了事情。我检查了bar
功能是否在期间可用,但它在外面无法生存。
forEach
回调创建一个闭包。 在这种封闭中定义的任何东西都是与世界关闭的。 您可以对代码的最终结果进行成像,使其等效于以下内容:
function() {
function bar() { ... }
function quux() { ... }
}
// bar and quux are out of scope here :(
如果您希望这些功能可供全世界使用,您将需要一些对象来附加这些函数。 window
是最便宜的,或者这样的东西更好一点:
var myScope = {};
['bar', 'quux'].forEach(function(i) {
eval('myScope["'+i+'"] = function(param) { this.param = param; return this; }');
});
myScope.bar(); // woo hoo!
['bar', 'quux'].forEach(function(i) {
this.eval('function '+i+'(param) { this.param = param; return this; }');
});
['bar', 'quux'].forEach(function(i) {
window.eval('function '+i+'(param) { this.param = param; return this; }');
});
['bar', 'quux'].forEach(function(i) {
eval.call(null, 'function ' + i + '(param) { this.param = param; return this; }');
// same
// eval.call(window, 'function ' + i + '(param) { this.param = param; return this; }');
});
forEach
的问题是eval
在匿名函数内运行,因此创建的变量将被限制在该范围内,无法从外部访问。
要修复它,只需以不需要包装函数的其他方式迭代数组。例如:
-
for
循环:var names = ['bar', 'quux']; for(var i=0; i<names.length; ++i) eval('function '+names[i]+'(param) { this.param = param; return this; }');
-
for...of
(ECMAScript 6)for(var i of ['bar', 'quux']) eval('function '+i+'(param) { this.param = param; return this; }');
请注意,这在严格模式下不起作用:
10.4.2.1 严格模式限制
评估代码无法实例化 调用 eval if 的调用上下文的变量环境 调用上下文的代码或评估代码是严格的 法典。相反,此类绑定在新的 只有评估代码才能访问的变量环境。
您可以简单地将函数分配给全局对象:
['bar', 'quux'].forEach(function(i) {
eval('window.' + i + ' = function(param) { this.param = param; return this; }');
});
还有一个答案!使用 window
对象:
['bar', 'quux'].forEach(function(i) {
eval('window.'+i+' = function(param) { this.param = param; return this; }');
});