說到setTimeout與setInrerval大家可能都覺得很easy,我剛接觸js的也是這樣的想法,可后來在知乎看到了一道題,大概好像是這樣的:
例一:
setTimeout(function(){
console.log("小馬“);
setTimeout(function(){arguments.callee;},1000);
},1000)
例二:
setInterval(function(){console.log("小馬“);},1000);
問一與二的區別?
說實話我剛看到這個題目的時候是懵比的,因為我覺得這兩者是完全一樣的呀,都是間隔1000ms之后執行回調的呀,可是既然這么問了肯定他們之間是有區別的,於是乎我就去查了相關的資料,果然,二者不僅僅是有差別的,而且定時器也顛覆了我以往的認知。
首先,這兩個定時器的基本含義我就不重復了,我覺得只要是個學前端的肯定沒有不知道的。為什么說定時器也顛覆了我以往的認知呢?因為我發現定時器的回調函數並不是相當於在時間到了就執行,而是有一個主js執行進程,這個進程是頁面剛加載的時候頁面按照加載順序執行的js代碼,此外還有一個需要在進程空閑的時候執行的代碼隊列,而我們所說的定時器的回調就是相當於(以上的例一為例)在1000ms之后把定時器回調放入到空閑隊列中(注意,空閑隊列有可能還有其它的代碼,比如點擊事件,因此定時器回調放入的位置不一定是空閑隊列的開始位置!)舉個例子:
var i=0;
function a(){
t=setTimeout(function(){console.log("小明")},0);
}
a();
alert(”小紅“);
此時你會發現先彈出小紅,又彈出的小明!!
好了,簡單的可以理解位定時器和js其他程序是並行執行的,不過jquery的作者有一篇文章專門介紹這個隊列的,有興趣的可以搜一下看看!!
接下來說第二點,就是例一與例二的區別:
setInterval有個很煩的地方就是當js主程序空閑時候,執行代碼隊列里面的代碼的時候,如果此時候我們有一個問題,定時器是等到回調執行完,才開始計時進行下次循環呢?還是只要一次計時完畢,插入回調之后不管回調執不執行就開始計時呢?答案顯然是后者,這也就是我說setInterval坑比的原因啊,因為這會出現一種情況,當我們插入回調的時候前隊列有別的代碼在執行,這時候回調肯定是不會執行的,因此如果這個時候無限定時時間到了會再次插入回調,這個時候如果發現隊列中的第一次回調沒有執行,那么再次插入的回調瀏覽器就默認取消,(這是以防出現回調連續執行多次的情況)但是這又引發了新的情況就是有些回調是不能取消掉的?
這就是我們經常使用例一代替例二的原因,例一可以避免上述的情況。累,很簡單的東西被我說的這么復雜,我也是醉了,看來文字功底還很欠缺,可是我的夢想是新時代的作家,這可咋整呢?