1

I'm trying to change the body background color that flashes by id change using recursive function, that functions by even/odd condition check and continues by incrementing the supplied parameter after each excution. I'm executing this function using DOM level zero event handler on-click. I'm seeing some weird results.

Here is the html/css with its javascript code. Also see the comments that were put in the code, that explains other weird problems.

<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

This jsfiddle does what you seem to want, however, it doesn't use recursion and it uses 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

Notice the starting class style0 for the body tag.

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

So, this may not be an acceptable answer for you but it does what it seems you wanted.

Edit: If you really want to use IDs instead of classes the following would more fit your question.

This jsfiddle uses IDs. Updated code is below.

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

Notice the starting id style0 for the body tag.

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

它似乎与alert()'s 一起“工作”而不是没有的原因是因为alert()'s 减慢了递归函数的执行速度,因此它是可感知的。否则,这一切都“有效”,无论是否有警报,但是您将"Maximum call stack size exceeded"在 Chrome 中遇到错误,例如仅仅因为它是一个无限循环。

要了解它的循环速度,请参阅这个演示,其中我重构了您的代码和document.write()循环编号。加载该页面时,它会在不到一秒的时间内达到 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/

更新一:快闪


另请注意,您可以将延迟更改为 ,0这将导致背景非常快速地闪烁,正如您可能想要的那样。

更新 2:堆叠超时


正如@rdp 所指出的,重复单击按钮会导致超时调用的堆叠。因此,如果您想防止这种情况发生,您始终可以在创建新超时之前清除之前的超时:

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

工作示例:http: //jsfiddle.net/RuTxu/2/

或者您可以通过设置一个布尔值一次只允许一个 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 回答