本文已参与「新人创作礼」活动,一起开启掘金创作之路。
接上一篇文章的JavaScript小记~~~
2.3.1 JavaScript计时器
在JavaScript中,我们可以在设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行。 计时器类型: 一次性计时器:仅在指定的延迟时间之后触发一次。 间隔性触发计时器:每隔一定的时间间隔就触发一次。 计时器方法:
2.3.1.1计时器setInterval()
在执行时,从载入页面后每隔指定的时间执行代码。setInterval
指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
语法:
setInterval(代码,交互时间);
参数说明:
- 代码:要调用的函数或要执行的代码串。
- 交互时间:周期性执行或调用表达式之间的时间间隔,以毫秒计(1s=1000ms)。
返回值:
一个可以传递给 clearInterval() 从而取消对"代码"的周期性执行的值。
调用函数格式( 假设有一个clock()函数 ):
setInterval("clock()",1000)
或
setInterval(clock,1000)
我们设置一个计时器,每隔100毫秒调用clock()函数,并将时间显示出来,代码如下:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>计时器</title>
<script type="text/javascript">
var int=setInterval(clock, 100)
function clock(){
var time=new Date();
document.getElementById("clock").value = time;
}
</script>
</head>
<body>
<form>
<input type="text" id="clock" size="50" />
</form>
</body>
</html>
下面是一个通过setInterval
方法实现网页动画的例子。
var div = document.getElementById('someDiv');
var opacity = 1;
var fader = setInterval(function() {
opacity -= 0.1;
if (opacity >= 0) {
div.style.opacity = opacity;
} else {
clearInterval(fader);
}
}, 100);
上面代码每隔100毫秒,设置一次div
元素的透明度,直至其完全透明为止。
setInterval
的一个常见用途是实现轮询。下面是一个轮询 URL 的 Hash 值是否发生变化的例子。
var hash = window.location.hash;
var hashWatcher = setInterval(function() {
if (window.location.hash != hash) {
updatePage();
}
}, 1000);
setInterval
指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。比如,setInterval
指定每 100ms 执行一次,每次执行需要 5ms,那么第一次执行结束后95毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105毫秒,那么它结束后,下一次执行就会立即开始。
为了确保两次执行之间有固定的间隔,可以不用setInterval
,而是每次执行结束后,使用setTimeout
指定下一次执行的具体时间。
var i = 1;
var timer = setTimeout(function f() {
// ...
timer = setTimeout(f, 2000);
}, 2000);
上面代码可以确保,下一次执行总是在本次执行结束之后的2000毫秒开始。
2.3.1.2取消计时器clearInterval()
clearInterval() 方法可取消由 setInterval() 设置的交互时间。
语法:
clearInterval(id_of_setInterval)
参数说明: id_of_setInterval:由 setInterval() 返回的 ID 值。
每隔 100 毫秒调用 clock() 函数,并显示时间。当点击按钮时,停止时间,代码如下:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>计时器</title>
<script type="text/javascript">
function clock(){
var time=new Date();
document.getElementById("clock").value = time;
}
// 每隔100毫秒调用clock函数,并将返回值赋值给i
var i=setInterval("clock()",100);
</script>
</head>
<body>
<form>
<input type="text" id="clock" size="50" />
<input type="button" value="Stop" onclick="clearInterval(i)" />
</form>
</body>
</html>
显示效果:
2.3.1.3计时器setTimeout()
setTimeout()计时器,在载入后延迟指定时间后,去执行一次表达式,仅执行一次。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。
var timerId = setTimeout(func|code, delay);
上面代码中,setTimeout
函数接受两个参数,第一个参数func|code
是将要推迟执行的函数名或者一段代码,第二个参数delay
是推迟执行的毫秒数。
语法:
setTimeout(代码,延迟时间);
参数说明:
- 要调用的函数或要执行的代码串。
- 延时时间:在执行代码前需等待的时间,以毫秒为单位(1s=1000ms)。
当我们打开网页3秒后,在弹出一个提示框,代码如下:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
setTimeout("alert('Hello!')", 3000 );
</script>
</head>
<body>
</body>
</html>
当按钮start被点击时,setTimeout()调用函数,在5秒后弹出一个提示框。
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function tinfo(){
var t=setTimeout("alert('Hello!')",5000);
}
</script>
</head>
<body>
<form>
<input type="button" value="start" onClick="tinfo()">
</form>
</body>
</html>
要创建一个运行于无穷循环中的计数器,我们需要编写一个函数来调用其自身。在下面的代码,当按钮被点击后,输入域便从0开始计数。
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
var num=0;
function numCount(){
document.getElementById('txt').value=num;
num=num+1;
setTimeout("numCount()",1000);
}
</script>
</head>
<body>
<form>
<input type="text" id="txt" />
<input type="button" value="Start" onClick="numCount()" />
</form>
</body>
</html>
如果推迟执行的是函数,就直接将函数名,作为setTimeout
的参数。
function f() {
console.log(2);
}
setTimeout(f, 1000);
setTimeout
的第二个参数如果省略,则默认为0。
setTimeout(f)
// 等同于
setTimeout(f, 0)
除了前两个参数,setTimeout
还允许更多的参数。它们将依次传入推迟执行的函数(回调函数)。
setTimeout(function (a,b) {
console.log(a + b);
}, 1000, 1, 1);
上面代码中,setTimeout
共有4个参数。最后那两个参数,将在1000毫秒之后回调函数执行时,作为回调函数的参数。
还有一个需要注意的地方,如果回调函数是对象的方法,那么setTimeout
使得方法内部的this
关键字指向全局环境,而不是定义时所在的那个对象。
var x = 1;
var obj = {
x: 2,
y: function () {
console.log(this.x);
}
};
setTimeout(obj.y, 1000) // 1
上面代码输出的是1,而不是2。因为当obj.y
在1000毫秒后运行时,this
所指向的已经不是obj
了,而是全局环境。
为了防止出现这个问题,一种解决方法是将obj.y
放入一个函数。
var x = 1;
var obj = {
x: 2,
y: function () {
console.log(this.x);
}
};
setTimeout(function () {
obj.y();
}, 1000);
// 2
上面代码中,obj.y
放在一个匿名函数之中,这使得obj.y
在obj
的作用域执行,而不是在全局作用域内执行,所以能够显示正确的值。
另一种解决方法是,使用bind
方法,将obj.y
这个方法绑定在obj
上面。
var x = 1;
var obj = {
x: 2,
y: function () {
console.log(this.x);
}
};
setTimeout(obj.y.bind(obj), 1000)
// 2
2.3.1.4取消计时器clearTimeout()
setTimeout()和clearTimeout()一起使用,停止计时器。
语法:
clearTimeout(id_of_setTimeout)
参数说明: id_of_setTimeout: 由 setTimeout() 返回的 ID 值。该值标识要取消的延迟执行代码块。
下面的例子和上节的无穷循环的例子相似。唯一不同是,现在我们添加了一个 "Stop" 按钮来停止这个计数器:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
var num=0,i;
function timedCount(){
document.getElementById('txt').value=num;
num=num+1;
i=setTimeout(timedCount,1000);
}
setTimeout(timedCount,1000);
function stopCount(){
clearTimeout(i);
}
</script>
</head>
<body>
<form>
<input type="text" id="txt">
<input type="button" value="Stop" onClick="stopCount()">
</form>
</body>
</html>
制作的一个简易的计时器:(框内数字随时间增长,发现一个有趣的事情,点start可以使计时加速)