我正在努力使用JavaScript在一个页面上放置三个计数器。当我运行此页面时,计数器出现但它们已冻结,请勿刷新。这是我的代码:
<!DOCTYPE html>
<head>
<meta charset="utf-8"/>
<title>Counters</title>
<script type="text/javascript">
function zero(element) {
if (element < 10) return element = "0" + element;
return element;
}
function counter(day, month, id) {
var year = (new Date).getFullYear();
var today = new Date();
var vDate = new Date(year,month-1,day,9,00);
var ms_day = 24 * 60 * 60 * 1000;
var diff = (vDate.getTime() - today.getTime());
var e_daysLeft = diff / ms_day;
var daysLeft = Math.floor(e_daysLeft);
var e_hoursLeft = (e_daysLeft - daysLeft)*24;
var hoursLeft = Math.floor(e_hoursLeft);
var e_minutesLeft = ((e_hoursLeft - hoursLeft)*60);
var minutesLeft = Math.floor(e_minutesLeft);
var e_secondsLeft = Math.floor((e_minutesLeft - minutesLeft)*60);
var secondsLeft = Math.floor(e_secondsLeft);
var text = 'Left: '
+daysLeft+' days, '
+hoursLeft+ ' hours, '
+minutesLeft+ ' minutes '
+zero(secondsLeft)+' seconds!'
var element = document.getElementById(id);
if (daysLeft+hoursLeft+minutesLeft+secondsLeft <= 0) {
element.innerHTML = 'Over' ;
} else {
element.innerHTML = text;
setTimeout("counter(day,month,id)",1000)
}
}
counter(14,2,'test7');
counter(27,3,'test8');
counter(30,6,'test9');
</script>
<body onload="counter(14,2,'test7'); counter(27,3,'test8'); counter(30,6,'test9');">
<div id="test7"></div>
<div id="test8"></div>
<div id="test9"></div>
</body>
</html>
你能告诉我为什么setTimeout("counter(day,month,id)",1000)
无效吗?
答案 0 :(得分:1)
setTimeout期望一个函数,而不仅仅是一个字符串,看看这里:http://www.w3schools.com/jsref/met_win_settimeout.asp
以下是修改后的工作版本:https://jsfiddle.net/3todtotp/
计数器
<script type="text/javascript">
function zero(element) {
if (element < 10) return element = "0" + element;
return element;
}
function counter(day, month, id) {
var year = (new Date).getFullYear();
var today = new Date();
var vDate = new Date(year,month-1,day,9,00);
var ms_day = 24 * 60 * 60 * 1000;
var diff = (vDate.getTime() - today.getTime());
var e_daysLeft = diff / ms_day;
var daysLeft = Math.floor(e_daysLeft);
var e_hoursLeft = (e_daysLeft - daysLeft)*24;
var hoursLeft = Math.floor(e_hoursLeft);
var e_minutesLeft = ((e_hoursLeft - hoursLeft)*60);
var minutesLeft = Math.floor(e_minutesLeft);
var e_secondsLeft = Math.floor((e_minutesLeft - minutesLeft)*60);
var secondsLeft = Math.floor(e_secondsLeft);
var text = 'Left: '
+daysLeft+' days, '
+hoursLeft+ ' hours, '
+minutesLeft+ ' minutes '
+zero(secondsLeft)+' seconds!'
var element = document.getElementById(id);
if (daysLeft+hoursLeft+minutesLeft+secondsLeft <= 0) {
element.innerHTML = 'Over' ;
} else {
element.innerHTML = text;
setTimeout(function(){counter(day,month,id)},1000)
}
}
counter(14,2,'test7');
counter(27,3,'test8');
counter(30,6,'test9');
</script>
<div id="test7"></div>
<div id="test8"></div>
<div id="test9"></div>
答案 1 :(得分:1)
正如其他人所指出的那样,你传递的是字符串文字而不是函数。
话虽如此,人们经常犯的典型后续错误是写setTimeout(counter(day, month, id))
。当您调用函数(甚至作为参数)时,会立即调用该函数。从运行时的角度来看,最终看起来就是这样。
counter(day, month, id)
并获取该调用的返回结果。在你的程序中,一旦完成循环遍历所有内容,该函数最终将返回null
。setTimeout(null, 1000)
,传递counter(day, month, id)
调用setTimeout(counter(day, month, id))
实际上只是作为简写:
var result = counter(day, month, id);
setTimeout(result, 1000);
这就是其他答案建议包装功能的原因:
setTimeout(function () {
counter(day, month, id);
}, 1000);
这样您仍然可以将所有参数传递给counter
,同时仍然将没有参数的函数传递给setTimeout。
更清洁的解决方案(至少对我而言)是使用bind,这有点像上述方法的更方便的简写:
setTimeout(counter.bind(this, day, month, id), 1000);
这超出了本答案的范围,但我喜欢bind
的原因是参数将通过值而不是引用传递,因此在使用它时,您不太可能遇到相关问题涉及循环内部javascript闭包的常见错误。重要的是要记住bind
在内部非常类似于手动包装方法。
在这两个实例中,您正在创建一个新函数,使用预定义的参数为您调用目标函数,然后传递新函数而不是原始函数。
答案 2 :(得分:0)
尝试setTimeout(function(){counter(day,month,id)},1000)所以这是一个给setTimeout而不是字符串的函数。