var Timer = setTimeout(function(){console.log(Timer);},1000);console.log(0);也可以写成字符串参数的形式,由于这种形式会造成javascript引擎两次解析,降低性能,故不建议使用
var Timer = setTimeout("console.log(Timer);",1000);console.log(0);如果省略setTimeout的第二个参数,则该参数默认为0
var Timer = setTimeout(function(){console.log(Timer);});console.log(0);实际上,除了前两个参数,setTimeout()方法还允许添加更多的参数,它们将被传入定时器中的函数中
setTimeout(function(a,b){console.log(a+b);},1000,1,1);可以使用IIFE传参来兼容IE9-浏览器的函数传参
setTimeout((function(a,b){return function(){console.log(a+b);}})(1,1),1000);或者将函数写在定时器外面,然后函数在定时器中的匿名函数中带参数调用
function test(a,b){console.log(a+b);}setTimeout(function(){test(1,1);},1000);this指向
var a = 0;function foo(){console.log(this.a);};var obj = {a : 2,foo:foo}setTimeout(obj.foo,100);//0//等价于var a = 0;setTimeout(function foo(){console.log(this.a);},100);//0若想获得obj对象中的a属性值,可以将obj.foo函数放置在定时器中的匿名函数中进行隐式绑定
var a = 0;function foo(){console.log(this.a);};var obj = {a : 2,foo:foo}setTimeout(function(){obj.foo();},100);//2或者也可以使用bind方法将foo()方法的this绑定到obj上
var a = 0;function foo(){console.log(this.a);};var obj = {a : 2,foo:foo}setTimeout(obj.foo.bind(obj),100);//2clearTimeout()
//过100ms后,控制台输出setTimeout()方法的返回值1var Timer = setTimeout(function(){console.log(Timer);},100);于是可以利用这个值来取消对应的定时器
var Timer = setTimeout(function(){console.log(Timer);},100);clearTimeout(Timer);或者直接使用返回值作为参数
var Timer = setTimeout(function(){console.log(Timer);},100);clearTimeout(1);一般来说,setTimeout返回的整数值是连续的,也就是说,第二个setTimeout方法返回的整数值比第一个的整数值大1
//控制台输出1、2、3var Timer1 = setTimeout(function(){console.log(Timer1);},100);var Timer2 = setTimeout(function(){console.log(Timer2);},100);var Timer3 = setTimeout(function(){console.log(Timer3);},100);setInterval()
<button id="btn">0</button><script>var timer = setInterval(function(){btn.innerHTML = Number(btn.innerHTML) + 1;},1000);btn.onclick = function(){clearInterval(timer);btn.innerHTML = 0;}</script>[注意]HTML5标准规定,setTimeout的最短时间间隔是4毫秒;setInterval的最短间隔时间是10毫秒,也就是说,小于10毫秒的时间间隔会被调整到10毫秒
setTimeout(function(){console.log(1);});console.log(0);实际上,把setTimeout的第二个参数设置为0s,并不是立即执行函数的意思,只是把函数放入代码队列
btn.onclick = function(){setTimeout(function(){console.log(1);},250);}如果上面代码中的onclick事件处理程序执行了300ms,那么定时器的代码至少要在定时器设置之后的300ms后才会被执行。队列中所有的代码都要等到JavaScript进程空闲之后才能执行,而不管它们是如何添加到队列中的
如图所示,尽管在255ms处添加了定时器代码,但这时候还不能执行,因为onclick事件处理程序仍在运行。定时器代码最早能执行的时机是在300ms处,即onclick事件处理程序结束之后
setInterval的问题
使用setInterval()的问题在于,定时器代码可能在代码再次被添加到队列之前还没有完成执行,结果导致定时器代码连续运行好几次,而之间没有任何停顿。而javascript引擎对这个问题的解决是:当使用setInterval()时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。这确保了定时器代码加入到队列中的最小时间间隔为指定间隔
但是,这样会导致两个问题:1、某些间隔被跳过;2、多个定时器的代码执行之间的间隔可能比预期的小
假设,某个onclick事件处理程序使用serInterval()设置了200ms间隔的定时器。如果事件处理程序花了300ms多一点时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过某间隔的情况
例子中的第一个定时器是在205ms处添加到队列中的,但是直到过了300ms处才能执行。当执行这个定时器代码时,在405ms处又给队列添加了另一个副本。在下一个间隔,即605ms处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中
迭代setTimeout
为了避免setInterval()定时器的问题,可以使用链式setTimeout()调用
setTimeout(function fn(){setTimeout(fn,interval);},interval);这个模式链式调用了setTimeout(),每次函数执行的时候都会创建一个新的定时器。第二个setTimeout()调用当前执行的函数,并为其设置另外一个定时器。这样做的好处是,在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。而且,它可以保证在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行
<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div><script>myDiv.onclick = function(){var timer = setInterval(function(){if(parseInt(myDiv.style.left) > 200){clearInterval(timer);return false;}myDiv.style.left = parseInt(myDiv.style.left) + 5 + "px"; },16); }</script>使用链式setTimeout()
<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div><script>myDiv.onclick = function(){setTimeout(function fn(){if(parseInt(myDiv.style.left) <= 200){setTimeout(fn,16); }else{return false;}myDiv.style.left = parseInt(myDiv.style.left) + 5 + "px"; },16); }</script>应用
<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;"></div><script>myDiv.onclick = function(){alert(0);}document.onclick = function(){alert(1);}</script>如果进行想让document的onclick事件先发生,即点击div元素,先弹出1,再弹出0。则进行如下设置
<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;"></div><script>myDiv.onclick = function(){setTimeout(function(){alert(0);})}document.onclick = function(){alert(1);}</script>【2】用户自定义的回调函数,通常在浏览器的默认动作之前触发。比如,用户在输入框输入文本,keypress事件会在浏览器接收文本之前触发。因此,下面的回调函数是达不到目的
<input type="text" id="myInput"><script>myInput.onkeypress = function(event) {this.value = this.value.toUpperCase();}</script>上面代码想在用户输入文本后,立即将字符转为大写。但是实际上,它只能将上一个字符转为大写,因为浏览器此时还没接收到文本,所以this.value取不到最新输入的那个字符
<input type="text" id="myInput"><script>myInput.onkeypress = function(event) {setTimeout(function(){myInput.value = myInput.value.toUpperCase();});}</script>代码到此结束。下篇给大家介绍