如何写函数-y接受参数-fct_x,它访问需要在函数-y中定义的var-a?

时间:2014-12-16 13:05:32

标签: javascript mongodb

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

问题:如何写一个函数-y如上所述,以便在函数-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个功能可用于地图缩减。 28函数之一是emit(key,value)。 (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以便能够为user-given-mapFunction调用这样的emit-function来调用?

[var a]相当于[function-emit]
[function y]相当于[function-mapReduce]
[function x]相当于[function-mapFunction]

2 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,那么您正在寻找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中不可能将变量注入某个函数的范围(同样,不依赖于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 ]
)




答案 1 :(得分:0)

以下答案由Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?

进行检查
function x() {
    return a + 1; // it can be anything accessing var-a.
}

function y(fct_x) {
    var a = 2;
    var x = eval("(" + String(fct_x) + ")"); // eval(String(fct_x)) will return undefined.
                                             // eval("(" + String(fct_x) + ")") will return a function
    console.log(x()); // 3 
}

y(x);   // exception: see above
        // x is any function which will access var-a which is required to be defined in function-y