1

我会直截了当:我有这个循环:

for (var i = 1; i <= toSchedule; i++) {
        when = trackWrapper.lastPlay +
                (trackDuration +
                (looper.timeInterval - trackDuration));

        track.play(true, when);
        trackWrapper.lastPlay = when;
    }

play方法在体内有这个:

[...]
// Here when is a different value for each call (verified)
// Many calls of the play method are performed before the returned function below is run as a callback
        function playingCallback(myWhen){

            return function(buffers){
                // Here myWhen will always be equal to the value of the last call occurred BEFORE the first callback execution
                console.log("myWhen = "+myWhen);
                [...]

            };
        };

        var realCallback = playingCallback(when);

        track.scheduled.push(when);
        track.recorder.getBuffer(realCallback);

因此,例如:

play(true, 1);
play(true, 2);
play(true, 3);

// Wait for it...

myWhen = 3;
myWhen = 3;
myWhen = 3;

现在:我读过关于闭包的文章,我读过“臭名昭​​著的循环问题”,我已经在 StackOverflow 上阅读了数十个答案,但我无法弄清楚这一点。这是我第二次遇到这种回调问题,所以,在这一点上,我想我还没有完全理解发生了什么。

您能否向我解释一下上面的代码应该有什么问题?先感谢您。

4

1 回答 1

1

通常,您应该了解以下规则:即使在范围已退出之后,一个clousure 也可以访问其“周围范围”。但这将是执行时范围的状态,而不是(!)闭包创建时的状态

如果您在循环内创建一个闭包,它将可以访问循环变量。但循环很可能已经结束。所以循环变量将保存其最后一个循环的值。

因此,如果您的闭包是回调,您应该在创建时创建相关范围变量的副本,并在执行时使用此副本。您可以通过从立即执行的匿名函数创建内部闭包来做到这一点(例如)

function myOuterScope(count) {
   for(i=0; i<count; i++) {
      setTimeout((function(local_i) {
         // this function will be immediately executed. local_i is a copy of i at creation time
         return function() {
            // this is the function that will be called as a callback to setTimeout
            // use local_i here, and it will be 0, 1, 2 instead of 3, 3, 3
         }
      })(i)
      , 1000);
   }
}
myOuterScope(3);
于 2013-09-26T13:25:50.503 回答