1

jQueryを使用して、ランダムな量のクラウドを生成してページのヘッダーに追加し、指定された間隔でそれらを左に移動しています。すべてが正常に機能しています。実行間隔は、クラウドごとに1回だけ実行され、再度実行されることはありません。これが私のコードです:

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(i){
      return function(){
         moveCloud(i);
      };
 })(cnt), 100);
于 2012-07-05T19:45:11.830 に答える
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)。この関数は、値を指定してi呼び出すmoveCloudと、その値を使用して呼び出します。次に、すぐにouter値を呼び出しますcntこれにより、この時点での値が何であれ、呼び出されたときに呼び出す関数が得られmoveCloudます。これはまさに私たちが望んでいることです!cnt

そしてそれが私たちがそのようにする理由です。

于 2012-07-05T19:56:43.677 に答える