传递函数作为参数

时间:2013-05-01 21:07:44

标签: javascript function closures

如何使用此代码通过引用传递此函数?

var Class = function() {
    var callback1;
    var callback2;

    function buildStuff(data, callback) {
        element.onclick = function() {
            doStuff(callback);
        };
    }

    function doStuff(callback) {
        callback();
    }

    return {
        "setCallback1":function(fn) {
            callback1 = fn;
        },
        "setCallback2":function(fn) {
            callback2 = fn;
        },
        //may rebuild with different data, but same callback
        "buildFoo":function(data) {
            buildStuff(data, callback1);
        },
        //may rebuild with different data, but same callback
        "buildBar":function(data) {
            buildStuff(data, callback2);
        }
    };
}

function main() {
    var object = Class();
    object.setCallback1(function() {
        //do stuff
    });
    object.setCallback2(function() {
        //do something else
    });
}

当您实际点击该元素时,callbackundefined。我希望它是我用setCallback函数设置的匿名函数,因为在我调用setCallback函数后发生了用户点击。

谢谢!

编辑:感谢您的投入。我应该提到我需要能够动态设置callback等于什么。因此,我不能从callback消除buildStuff参数。

EDIT2:对于这种混乱感到非常抱歉;我意识到我的例子有点过于偏离上下文来展示我在做什么。 buildStuff实际上是一个重复调用的私有成员函数(使用模块模式)。根据正在构建的内容,它需要不同的回调。回调实际上是在类之外设置的(好吧,模块模式类),所以它必须是动态的。我已经更新了我的代码,再次,抱歉这个坏的例子。

2 个答案:

答案 0 :(得分:3)

您在buildStuff中创建的单击处理程序会在局部变量上创建一个闭包。您已将callback传递给buildStuff功能,但在您通过该功能时,它会undefined。由于这会影响其他 callback变量,因此您始终会看到undefined,而不是其他的状态 callback变量。

相反,请勿将参数传递给buildStuff,并且会创建闭包,并捕获您想要的callback变量。

function buildStuff() {
    element.onclick = function() {
        doStuff(callback);
    };
}

想象一下;

  1. 您的全局变量callback 指向一个值(在本例中为undefined)。
  2. 当您buildStuff中的main()时,您将回调(undefined)指向的值作为参数传递给buildStuff
  3. 您的点击处理程序会在局部变量+范围内的其他变量上创建一个闭包(请注意本地 callback 阴影全局callback) 。您的事件处理程序中的callback现在为undefined
  4. 然后 setCallbacksetCallback使用callback运算符更改全局=变量指向的值。全局callback和本地callback现在指向不同的值,这就是您在事件处理程序更新中看不到callback的原因。

    在这种情况下你想要做的是更改callback指向的值,因此指向那里的其他变量也会更新,但JavaScript并不允许你这样做。

    < / LI>

答案 1 :(得分:2)

是的,但您已在buildStuff之前致电setCallback

将使用当时callback的内容(未定义)。

如果您想使用不同的回调来呼叫buildStuff,请执行此操作,并消除多余的setCallback

function buildStuff(callback) {
    element.onclick = function() {
        doStuff(callback);
    };
}

function doStuff(callback) {
    callback();
}

function main() {
    buildStuff(  
      function() {
        //do something
      }
    );
}