写定时器分两种写法,setInterval和setTimeout。
先来说setInterval:
setInterval(code,millisec[,"lang"])
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
再来说说setTimeout:
setTimeout(code,millisec)
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。
setTimeout() 只执行 code 一次。如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout()。
通过分析可以得出一个结论,如果要做一个定时器的应用,setInterval可以使用匿名函数实现,setTimeout却不可以。例如: 如果使用setTimeout实现定时器,则需要首先定义一个函数,之后使用 setTimeout() 调用该函数,最后在该函数中再次调用 setTimeout()。
如果按照这个逻辑代码应该是这样的:
运行后却发现有错误:Uncaught ReferenceError: redraw is not defined。
如果运行代码没在 window.onload = function(){}环境下,即把 window.onload = function(){} 方法去除:
这样错误就消失了,为什么呢?如果换成setInterval调用呢? 发现会报同样的错误:Uncaught ReferenceError: redraw is not defined。
说到这里也就明了了,因为无论是setInterval还是setTimeout都只能调用全局函数,即挂在window下的函数。
那么解决方案是什么呢?
既然发现了问题是无论setInterval还是setTimeout都只能调用全局函数,
那么只要把redraw函数放到window.onload方法外面定义就可以解决这个棘手问题。还拿setTimeout为例:
注意一:调用函数时如果函数名外加了引号,则()也要写上,如setTimeout('redraw()',30),不然虽然不会报错,但程序也不会执行。
可以不加引号,只写函数名,如setTimeout(redraw,30),或则函数名(),如setTimeout(redraw(),30)。
注意二:调用函数传递参数时,尽可能使用不带引号的方式传递,因为在加引号的情况下传递参数会出现各种问题,这里就不一一介绍了。
还没完,运行了代码发现又有错误:Uncaught RangeError: Maximum call stack size exceeded.
翻译过来就是因为递归次数太多导致内存被耗费太多。真是坑爹啊。
最后在网上找的一个方法_setTimeout替代setTimeout方法,具体原理就不解释了,其实我也不太懂。☺
完整无误的JS代码:
源引:http://www.58lou.com/separticle.php?artid=202
先来说setInterval:
setInterval(code,millisec[,"lang"])
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
再来说说setTimeout:
setTimeout(code,millisec)
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。
setTimeout() 只执行 code 一次。如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout()。
通过分析可以得出一个结论,如果要做一个定时器的应用,setInterval可以使用匿名函数实现,setTimeout却不可以。例如: 如果使用setTimeout实现定时器,则需要首先定义一个函数,之后使用 setTimeout() 调用该函数,最后在该函数中再次调用 setTimeout()。
如果按照这个逻辑代码应该是这样的:
运行后却发现有错误:Uncaught ReferenceError: redraw is not defined。
如果运行代码没在 window.onload = function(){}环境下,即把 window.onload = function(){} 方法去除:
这样错误就消失了,为什么呢?如果换成setInterval调用呢? 发现会报同样的错误:Uncaught ReferenceError: redraw is not defined。
说到这里也就明了了,因为无论是setInterval还是setTimeout都只能调用全局函数,即挂在window下的函数。
那么解决方案是什么呢?
既然发现了问题是无论setInterval还是setTimeout都只能调用全局函数,
那么只要把redraw函数放到window.onload方法外面定义就可以解决这个棘手问题。还拿setTimeout为例:
注意一:调用函数时如果函数名外加了引号,则()也要写上,如setTimeout('redraw()',30),不然虽然不会报错,但程序也不会执行。
可以不加引号,只写函数名,如setTimeout(redraw,30),或则函数名(),如setTimeout(redraw(),30)。
注意二:调用函数传递参数时,尽可能使用不带引号的方式传递,因为在加引号的情况下传递参数会出现各种问题,这里就不一一介绍了。
还没完,运行了代码发现又有错误:Uncaught RangeError: Maximum call stack size exceeded.
翻译过来就是因为递归次数太多导致内存被耗费太多。真是坑爹啊。
最后在网上找的一个方法_setTimeout替代setTimeout方法,具体原理就不解释了,其实我也不太懂。☺
完整无误的JS代码:
具体效果请运行下面完整代码:
<!DOCTYPE html>
<html>
<head>
<meta http_equiv="Content_Type" content="text/html; charset=utf-8" />
<title>canvas</title>
<style type="text/css">
#cv { background-color:#000; margin-left:420px; margin-top:100px; }
</style>
</head>
<body>
<canvas id="cv" width="400" height="400">
<p>该浏览器不支持canvas。</p>
</canvas> <!-- canvas画布默认宽300px,高150px,背景颜色为白色 -->
<script type="text/javascript">
window.onload = function(){
var oC = document.getElementById('cv'),
oGC = oC.getContext('2d'),
width = 100,
height = 100,
param = {
oC:oC,
oGC:oGC,
step:step,
width:width,
height:height
};
oGC.fillStyle = 'rgba(0,255,255,1)';
oGC.fillRect(0,0,width,height);
_setTimeout(redraw,30,param);
}
var step = 0;
function redraw(param){
var oC = param.oC,
oGC = param.oGC,
width = param.width,
height = param.height;
step++;
oGC.clearRect(0,0,oC.width,oC.height);
oGC.fillRect(step,step,width,height);
_setTimeout(redraw,30,param);
}
function _setTimeout(callback,timeout,param){
var args = Array.prototype.slice.call(arguments,2);
var _cb = function(){
callback.apply(null,args);
}
setTimeout(_cb,timeout);
}
</script>
</body>
</html>
源引:http://www.58lou.com/separticle.php?artid=202