一页上有两个计数器

时间:2016-01-06 12:13:30

标签: javascript

我正在努力使用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)无效吗?

3 个答案:

答案 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而不是字符串的函数。