function x() {
return a + 1; // it can be anything accessing var-a.
}
function y(fct_x) {
var a = 2;
fct_x(); // exception: a is not defined
}
y(x); // exception: see above
// x is any function which will access var-a which is required to be defined in function-y
问题:如何像上面那样编写一个 function-y 以便在 function-y 中调用 fct_x() 不会抛出异常?
注意:fct_x 是访问 var-a 的任何函数(用户给定)。 var-a 未在 function-x 中定义,但需要在 function-y 中定义。
引用Is it possible to achieve dynamic scoping in JavaScript without resorting to eval? ,我尝试过 this ,但它不起作用。
为什么我问以上问题: 这个问题来自“MongoDB mapReduce”,像这样: 有 3 个属性和 28 个函数可用于 map 缩减。 emit(key,value) 是 28 个函数之一。 (See MongoDB doc) .
举个例子,
function mapFunction() { emit(this.fieldA, this.fieldB) };
db.collection.mapReduce(mapFunction, reduceFunction, {...}); // calling mapReduce-function
mapFunction中的emit-function没有在mapFunction中定义。它是在函数 db.collection.mapReduce 中的某处“提供”/“定义”的。如何编写 function-db.collection.mapReduce 以便能够为用户给定的mapFunction 提供这样的发出函数来调用?
[var a] 等价于 [function-emit]
[function y] 相当于 [function-mapReduce]
[function x] 相当于 [function-mapFunction]
最佳答案
如果我正确理解你的问题,你正在寻找 dynamic scoping 。 Javascript 是有词法作用域的,因此要捕获变量,闭包必须在文本上位于其作用域内。否则,这是不可能的,不包括或多或少的愚蠢技巧,例如:
function makeClosure(context) {
return function() {
return context("a") + 1;
};
}
function y(evalThis) {
var a = 2;
if(evalThis)
return eval(evalThis);
return makeClosure(y);
}
closure = y();
document.write(closure()) // 3
另请参阅Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?了解更多讨论和示例。
具体到你的 MongoDB 问题,在纯 JavaScript 中不可能将变量注入(inject)到某个函数的作用域中(同样,不诉诸 eval)。但是Mongo的map-reduce是用C++编写的,而不是用JS编写的,并且可以以任意方式操作范围:
_scope->setFunction("emit", etc
请参阅source .
为了完整起见,下面是一个使用 eval
的示例:
function map(ary, fun) {
// define some locals
var LOCAL = 42;
// re-evaluate the function within the scope
eval("fun=" + fun);
// now fun sees our locals
return ary.map(fun);
}
document.write(
map([1,2,3], function(x) { return x * LOCAL }) // [ 42, 84, 126 ]
)
关于javascript - 如何编写接受参数 fct_x 的函数 y,该参数 fct_x 访问需要在函数 y 中定义的 var-a?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27505345/