1

次のコードにエラーがあります。

generate: function() {
    var generated = [];
    for (var j = 0; j < objectDefinitions.length; j++) {
        var randomNumber;

        if (!objectDefinitions[j].restrictGeneration) {
            continue;
        }

        randomNumber = Math.random();

        if (randomNumber < objectDefinitions[j].probability) {
            generated.push(objectDefinitions[j].createObject());
            objectDefinitions[j].restrictGeneration = true;
            if (j > 5) {
            }
            setTimeout(function() {                 
                //console.log(j);
                objectDefinitions[j].restrictGeneration = false;
            }, objectDefinitions[j].cooldown);
        }
    }
    return generated;
}

setTimeoutが変数jを「起動」すると、変数jは6になります。これにより、配列には6つの項目しかないため、配列インデックスの範囲外の例外が発生します。何が起こっているのかよくわかりません。setTimeoutの外でjをチェックしましたが、6になることはありませんが、宣言後に変更されるようです。助けてくれてありがとう。

4

3 に答える 3

1

読み取る変数jはループで使用した変数であるため、「コピー」されませんでした。

setTimeout(
    (function(k){
        return function() {            
            objectDefinitions[k].restrictGeneration = false;
        };
    }(j))
, objectDefinitions[j].cooldown);

このようにjして、変数にコピーされkます。ただしk、ループの反復ごとに1つの変数があります。

于 2013-02-01T23:14:45.857 に答える
0

空のifステートメントが(何もしないことで)実行されると、jは5より大きいまま、設定されたタイムアウトに移行します。

基本的に、ifステートメントの後にさらにコードを実行するのではなく、その時点で終了するか、そこでelseステートメントを作成して、j>5の場合にそれ以上コードが実行されないようにする必要があります。

于 2013-02-01T23:15:06.733 に答える
0

これは閉鎖によるものです。

の値が表示さ6れているj++のは、最後にもう一度実行されて、forループの終了をトリガーしているためです。したがって、そのクロージャjは6になります。setTimeout実行時(forループが完了した後)は、そのクロージャのコンテキストで実行されます。

このコードを独自のクロージャーに移動する必要があります。これは、独自の関数に移動することによって行われます。何かのようなもの:

generate: function() {
    var generated = [];
    for (var j = 0; j < objectDefinitions.length; j++)
    {
       handleIteration(generated, j); // Re-factor your code into a new function
    }

    return generated;
}
于 2013-02-01T23:56:12.413 に答える