1

我正在使用 jQuery 生成随机数量的云并将其添加到页面的标题中,并在指定的时间间隔内将它们向左移动。一切正常,除了间隔只为每个云运行一次,而不是再次运行。这是我的代码:

if(enableClouds) {
    var cloudCount = Math.floor(Math.random() * 11); // Random Number between 1 & 10

    for(cnt = 0; cnt < cloudCount; cnt++) {
        var cloudNumber = Math.floor(Math.random() * 4);
        var headerHeight = $('header').height() / 2;
        var cloudLeft = Math.floor(Math.random() * docWidth);
        var cloudTop = 0;
        var thisHeight = 0;
        var cloudType = "one";

        if(cloudNumber == 2) {
            cloudType = "two";
        }else if(cloudNumber == 3) {
            cloudType = "three";
        }

        $('header').append('<div id="cloud' + cnt + '" class="cloud ' + cloudType + '"></div>');

        thisHeight = $('#cloud' + cnt).height();
        headerHeight -= thisHeight;
        cloudTop = Math.floor(Math.random() * headerHeight);

        $('#cloud' + cnt).css({
            'left' : cloudLeft,
            'top' : cloudTop
        });

        setInterval(moveCloud(cnt), 100);
    }

    function moveCloud(cloud) {
        var thisLeft = $('#cloud' + cloud).css('left');

        alert(thisLeft);
    }
}

任何帮助表示赞赏!

4

2 回答 2

2

工程师给了你你需要的代码。这是正在发生的事情。

setInterval函数接受一个 Function 对象和一个区间。Function 对象只是一个可以调用的对象,如下所示:

/* Create it */
var func = function() { /* ... blah ... */};

/* Call it */
var returnVal =  func(parameters)

这里的对象是func。如果你调用它,你得到的是返回值。

因此,在您的代码中:

setInterval(moveCloud(cnt), 100);

您正在提供setInterval调用的返回值moveCloud(cnt),而不是函数对象moveCloud。所以那一点被打破了。

一个不正确的实现是:

for(cnt = 0; cnt < cloudCount; cnt++) {
    /* ... other stuff ... */
    var interval = setInterval(function() {
       moveCloud(cnt);
    }, 100);
}

现在,您正在为它提供一个函数对象,这是正确的。当这个函数对象被调用时,它会调用moveCloud. 这里的问题是cnt.

你在这里创建的是一个闭包。您捕获对变量的引用cnt。当您传递给的函数对象setInterval被调用时,它会看到对的引用cnt并尝试解析它。当它这样做时,它会到达您迭代的变量,查看它的值并发现它等于cloudCount。问题是,没有映射到您创建的云(您有云 0 到 (cloudCount -1)),所以充其量不会发生任何事情,最坏的情况是您会收到错误消息。

正确的做法是:

 setInterval((function(i){
      return function(){
         moveCloud(i);
      };
 })(cnt), 100);

这使用返回函数的“立即函数”。您创建一个函数:

function(i){
    return function(){
        moveCloud(i);
    };
}

它返回另一个函数(让我们称之为它outer),当使用 valuei调用moveCloud时,使用该值调用。然后,我们立即outer用我们的 value调用cnt。这给了我们一个函数,当被调用时,它会moveCloud使用此时的任何值来cnt调用。这正是我们想要的!

这就是我们这样做的原因。

于 2012-07-05T19:56:43.677 回答
2

这是要走的路:

 setInterval((function(i){
      return function(){
         moveCloud(i);
      };
 })(cnt), 100);
于 2012-07-05T19:45:11.830 回答