使用递归函数更改背景背景颜色切换css id

时间:2013-05-06 00:16:24

标签: javascript recursion

我正在尝试使用递归函数更改通过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>

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

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

要了解它的循环速度,请参阅此演示I refactored your code and document.write() the loop number。加载该页面会在不到一秒的时间内达到15,000,然后才能达到最大调用堆栈。

答案 2 :(得分: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/

或者您只能通过设置布尔值来允许一次调用setTime:

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

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

但当然,所有这些都取决于您的具体用例