1

偶数/奇数条件チェックによって機能し、各実行後に指定されたパラメーターをインクリメントすることによって継続する、再帰関数を使用した ID 変更によって点滅するボディの背景色を変更しようとしています。DOM レベル ゼロ イベント ハンドラのオンクリックを使用して、この関数を実行しています。奇妙な結果が表示されます。

これは、javascript コードを含む html/css です。また、コードに追加されたコメントも参照してください。これは、他の奇妙な問題を説明しています。

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
    <style>
        #style1 {
            background:red;
        }
        #style2 {
            background:black;
        }
    </style>
</head>

<body>
    <input name="" type="button" value="Style Changer" id="button1" />
    <script>
        var button = document.getElementById("button1");
        var background = function (y) {
            alert(y); // results of background change or rest of the code only works if this alert is there which is what I don't really understand 
            if(y % 2 === 0) {
                alert(y); // weird result: this shows 2 for no reason.
                document.body.id = "style1"; // value supplied to the parameter y is 1 but taking the css property that suppose to take when the y is an even number. 
                var y = y + 1;
                background(y);
            } // End If
            else {
                document.body.id = "style2";
                var y = y + 1;
                background(y);
            } //End Else

        } // End of function
        button.onclick = function () {
            var x = 1;
            background(x);
        }

         // Another big problem: Last but not least remove all the alert function and it will not work as it worked when there were alerts in the code.
    </script>
</body>
4

3 に答える 3

1

このjsfiddleは、あなたが望むように見えますが、再帰を使用せず、jqueryを使用しています。

CSS

    .style0 {
        background-color: red;
    }
    .style1 {
        background-color: black;
    }

JavaScript/JQuery

    $(function () {
        var i = 0
        var background = function () {
            $("body").removeClass()
                .addClass("style" + i);

            i = ((i + 1) % 2); //To cycle from 0 to 1
        }

        var intervalID = undefined;
        $('#start').click(function () {
            if (intervalID != undefined) {
                clearInterval(intervalID);
            }
            intervalID = setInterval(background, 500);
        });
    });

HTML

body タグの開始クラス style0 に注目してください。

    <body class="style0">
        <button id="start">Start</button>
    </body>

したがって、これはあなたにとって受け入れられる答えではないかもしれませんが、あなたが望んでいるように見えます.

編集:クラスの代わりにIDを本当に使用したい場合は、次のほうが質問に適しています。

このjsfiddleは ID を使用します。更新されたコードは以下のとおりです。

CSS

    #style0 {
        background-color: red;
    }
    #style1 {
        background-color: black;
    }

JavaScript/JQuery

    $(function () {
        var i = 0
        var background = function () {
            $("body").attr("id", "style" + i);

            i = ((i + 1) % 2); //To cycle from 0 to 1
        }

        var intervalID = undefined;
        $('#start').click(function () {
            if (intervalID != undefined) {
                clearInterval(intervalID);
            }
            intervalID = setInterval(background, 500);
        });
    });

HTML

body タグの開始 ID style0 に注意してください。

    <body id="style0">
        <button id="start">Start</button>
    </body>
于 2013-05-06T14:13:49.550 に答える
0

alert()がなくても「動作」するように見える理由はalert()、 が再帰関数の実行を遅くして認識できるようにするためです。それ以外の場合、アラートの有無にかかわらず、これはすべて「機能」しますが"Maximum call stack size exceeded"、たとえば無限ループであるため、Chromeでエラーが発生します。

ループの速さを理解するには、コードとループ番号をリファクタリングdocument.write()したこのデモを参照してください。そのページをロードすると、呼び出しスタックの最大値に達する前に、1 秒もかからずに 15,000 に達します。

于 2013-05-06T00:35:16.550 に答える
0

実際の問題が何を解決したいのかよくわかりません。

しかし、あなたのコードは無限ループになり、例外が発生します(コンソール出力を確認してください):

Maximum call stack size exceeded

これは、再帰呼び出しの発生が速すぎるためです。ただし、アラートを使用すると、アラート ボックスが表示されている限り、コードの実行は基本的に一時停止されます。

わずかな時間遅延を追加することで、「実行速度が速すぎる」コードを打ち消すことができます。

var delay = 300;   // 300ms delay

var background = function(y){
    if( y%2 === 0){
        document.body.id = 'style1';
        setTimeout(function(){ background(y+1) }, delay);
    } else {
        document.body.id = 'style2';
        setTimeout(function(){ background(y+1) }, delay);
    }
}

作業例: http://jsfiddle.net/D7pBx/

更新 1: 高速点滅


また、遅延を変更して、0意図したとおりに背景が非常に速くちらつくようにすることもできます。

更新 2: スタック タイムアウト


@rdp が指摘したように、ボタンを繰り返しクリックすると、タイムアウト呼び出しがスタックされます。したがって、それが起こらないようにしたい場合は、新しいタイムアウトを作成する前に、以前のタイムアウトをいつでもクリアできます。

clearTimeout(t);
t = setTimeout(function(){ backgound(y+1) }, delay);

作業例: http://jsfiddle.net/RuTxu/2/

または、ブール値を設定して、一度に 1 つの setTimeout 呼び出しのみを許可することもできます。

if(busy) return;
busy = true;
setTimeout(function(){ 
    busy = false;
    backgound(y+1) 
}, delay);

作業例: http://jsfiddle.net/RuTxu/3/

もちろん、これはすべて特定のユースケースに依存します

于 2013-05-06T00:43:18.577 に答える