今天没事翻了翻JS高程,看到了setTimeout部分有这么一句话:调用setTimeout()之后,该方法会返回一个数值ID,表示超时调用。这个超时调用ID是计划执行代码的唯一标识符,可以通过它来取消超时调用。
然后我从书中上下左右找了半天也没发现有说这个ID的地方,于是乎抱着钻牛角尖的心态我去试了试,发现了一些很有意思的东西。
var id1 =setTimeout(function(){},10);
var id2 =setTimeout(function(){},10);
console.log(id1); //1
console.log(id2); //2
这个不是重点,重点是我又试了一下setInterval():
var id3 =setInterval(function(){},10);
console.log(id3); //3
也就是说这两个函数的id值是顺次创建的,一般情况下我们想要清除一个setTimeout()需要这么做:
clearTimeout(id1);
于是我想既然我们知道了它的id值是不是可以直接去清除呢?我就试了一下:
clearTimeout(1);
OK,成功了,完全没有问题!接着我又想既然他俩的id值都是数字能不能混着清除?然后又试了一下:
clearTimeout(id3);
还是成功了!这俩居然能够混用,我也是醉了。好吧,这个真是神奇,有必要记下来。
接下来再说说这setTImeout()别的方面的一些特点吧。
setTimeout()这个函数的第二个值是一个毫秒数,不能设置成0,或者说设置成0也没啥用,因为H5里面规定了它的最小值是4,也就是说小于4的人家会给你自动加上。
假设可以是0的话下面这个结果也永远是1,3,2:
console.log(1);
setTimeout(function(){console.log(2)},0);
console.log(3);
为什么呢?这就要说到JS语言的特性上了,JS这门语言创作的目的就是为了高效、简单、快捷,所以创作初始就将它定成了一门单线程的语言,但是如果真是单线程的话又会出现很多的问题,比如说事件堵塞,每一个任务执行完了才能去执行下一个任务。打个比方:你朋友中午要来你家吃饭,你决定要给他做几个菜,其中有一道糖醋鱼,会做饭的人都知道做鱼要提前把鱼用调料腌上半天鱼肉才能入味,你早上把鱼腌上了,然后你就在旁边等这个鱼腌好,等了一上午鱼终于腌好了你才发现没有买别的菜,朋友这时候来你家做客你一道菜也没有做好,尴尬了。这就类似于一个单线程的任务,一个执行完了才能执行另一个,其中有大量的等待时间,造成了资源的浪费和任务的堵塞。JS为了解决这个问题引入了异步处理的方法,也就是说你腌了鱼直接扔一边接着去干别的事情,等别的事情弄好了再回来看看鱼腌好没。
Web Work中规定了JS可以拥有多线程,但是同一时间只能拥有一个主线程,除了主线程其他线程不允许任何的dom操作,也就是说其他的线程类似于辅助线程。主线程中有一个执行栈,栈中的任务如果是同步执行结束了就会释放掉,如果是异步则会执行后进入辅助线程的任务队列之中,执行栈中如果空了主线程就会重新查找任务队列中的任务来执行,这叫做任务轮询。而今天我们的主角setTimeout也是一个异步的操作,而且比较不受待见,只有执行栈和任务队列中的任务全部执行完了才会去执行它,也就是说后面这个时间就是一个虚的数字,并不是真正意义上的执行后延时,因此即使它是0,也会是最后执行。
吐槽一句写博客真是挺累的,打了没多久手都酸了,还是敲代码来的省事。最后再说说setTimeout这个函数的另一个用法吧,就是设定计时器:
//计时器
var num = 0;
var max = 10;
function setTime()
{
num++;
console.log(num);
if(num<max){
setTimeout(setTime,1000);
}else{
console.log("Done");
}
}
setTime();
因为setInterval会一直循环如果忘了清除的话有可能会给用户带来不小的困扰,因此做一个计时器来有限次的执行是有很有必要的,当然,setInterval也并不是一无是处,比如常见的轮播图就离不开它,好吧其实setTimeout也能实现它,本来想夸两句的结果又把它黑了。