我正在尝试使用递归函数更改通过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>
答案 0 :(得分:1)
此 jsfiddle 执行您想要的操作,但是,它不使用递归,而是使用jquery。
.style0 {
background-color: red;
}
.style1 {
background-color: black;
}
$(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);
});
});
注意body标签的起始类style0。
<body class="style0">
<button id="start">Start</button>
</body>
所以,这对你来说可能不是一个可接受的答案,但它可以做你想要的。
编辑:如果您真的想使用ID而不是类,以下内容更适合您的问题。
此 jsfiddle 使用ID。更新后的代码如下。
#style0 {
background-color: red;
}
#style1 {
background-color: black;
}
$(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);
});
});
注意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/
另请注意,您可以将延迟更改为0
,这会导致背景快速闪烁,如您所愿。
正如@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/
但当然,所有这些都取决于您的具体用例