如何理解JavaScript單線程及setTimeout定時器

如何理解JavaScript單線程及setTimeout定時器,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

成都創(chuàng)新互聯(lián)主營郊區(qū)網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都App制作,郊區(qū)h5小程序設(shè)計搭建,郊區(qū)網(wǎng)站營銷推廣歡迎郊區(qū)等地區(qū)企業(yè)咨詢

理解JavaScript的單線程的理念對于JavaScript學(xué)習(xí),以及掌握其中的一些設(shè)計機制非常重要,比如回調(diào)、定時器。對于后續(xù)學(xué)習(xí)NodeJS也有很大的幫助。

通過先demo,后總結(jié)的形式,使得JavaScript的單線程更易于明白。

1 var a = 1;  //全局變量a 2 function test(){ 3     var a=2;  //test中變量a 4     setTimeout(function(){ 5         alert(a); //輸出test中變量a 6         a=3;  //修改test中變量a 7     },3000); 8     a=4; //修改test中變量a 9     setTimeout(function(){ 10         alert(a); //輸出test中變量a 11         a=5; //修改test中變量a 12    },1000); 13    alert(a); //輸出test中變量a 14 } 15 test(); //執(zhí)行test函數(shù) 16 alert(a); //輸出全局變量a  //運行結(jié)果:4 1 4 5  /* 結(jié)果解析:先輸出test()運行結(jié)果4,然后輸出之后一行代碼的1,然后1000ms之后輸出test()中的變量a=4,***3000ms之后輸出test()中的變量a=5 */  /*   運行機制:      1. JavaScript是單線程,從上往下依次執(zhí)行      2. setTimeout異步方法存放在任務(wù)隊列中,JS主線程執(zhí)行完成之后,才會取任務(wù)隊列中的任務(wù)到JS主線程中執(zhí)行!       -> 先執(zhí)行15行,然后執(zhí)行16行      -> 執(zhí)行15行,調(diào)用test()方法      -> 調(diào)用test()方法,先創(chuàng)建一個a變量,然后將***個setTimeout放到setTimeout對應(yīng)的線程中執(zhí)行(啟動定時器timer),第8行,修改test中變量a為4,然后將第二個setTimeout添加到setTimeout對應(yīng)的線程隊列中執(zhí)行,執(zhí)行13行,輸出test中變量a,此時為4;然后執(zhí)行16行,輸出全局變量a,此時為1.      -> 1000ms之后,將第二個setTimeout的回調(diào)函數(shù),添加到JS任務(wù)隊列中,3000ms后將***個setTimeout的回調(diào)函數(shù),添加到JS任務(wù)隊列中。      -> JS主線程執(zhí)行完成之后,會執(zhí)行任務(wù)隊列的事件,第二個setTimeout優(yōu)先進入任務(wù)隊列,所以優(yōu)先執(zhí)行,執(zhí)行第10行,輸出test中的變量a,值為4,然后di11行,將test中的變量a修改為5;2000ms之后***個setTimeout進入任務(wù)隊列,此時JS主線程棧為空,所以將其添加到JS主線程進行執(zhí)行,第5行,輸出test中的變量a,此時變量的值為5,第6行修改test變量a為3. */

由此延伸以下代碼:

var a = 1; var date = +new Date(); // 小技巧:通過"+"轉(zhuǎn)換為整數(shù) function test(){     var a=2;      setTimeout(function(){         console.log(a+'--'+ (new Date()-date));         a=3;        },3000);     a=4;     setTimeout(function(){         console.log(a+'--'+ (new Date()-date));         a=5;    },1000);    console.log(a+'--'+ (new Date()-date)); } while(new Date-date <1000){  } test(); console.log(a+'--'+ (new Date()-date));  //執(zhí)行結(jié)果:4-1000 1-1001 4-2000 5-4001

結(jié)合以下博客,整理一些重要概念:

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

http://www.cnblogs.com/Mainz/p/3552717.html

1、作為腳本語言,JavaScript主要功能是與用戶互動,以及操作DOM。假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內(nèi)容,另一個線程刪除了這個節(jié)點,這時瀏覽器應(yīng)該以哪個線程為準?  ->So: JavaScript就是單線程。

2、JavaScript的任務(wù)分成兩種:同步任務(wù)和異步任務(wù)。同步任務(wù):在主線程上排隊執(zhí)行的任務(wù),只有上一個任務(wù)執(zhí)行完成了,才會執(zhí)行下一個任務(wù)。異步任務(wù):不進入主線程,而進入“任務(wù)隊列”的任務(wù),只有“任務(wù)隊列”通知主線程,某個任務(wù)隊列可以執(zhí)行了,等主線程執(zhí)行完成,任務(wù)隊列才會進入主線程執(zhí)行。  -> So:只要主線程空了,就會去讀“任務(wù)隊列”,這就是JavaScript的運行機制。

3、主線程從“任務(wù)隊列”中讀取事件,這個過程是循環(huán)不斷的,所以整個事件又叫“事件循環(huán)”(Event Loop)。

HTML5規(guī)定setTimeout()的第二個參數(shù)的最小值(最短間隔),不得低于4ms,如果低于4ms就會自動增加。在此之前,老版本瀏覽的都將最短時間設(shè)置為10ms。另外,對于那些DOM變動(尤其是設(shè)計頁面重新渲染的部分),通常不會立即執(zhí)行,而是每16ms執(zhí)行一次。這是使用requestAnimationFrame()的效果要好于setTimeout()。

4、需要注意的是:setTimeout只是將事件插入“事件隊列”,必須等到前面代碼(執(zhí)行棧)執(zhí)行完,主線程才會去執(zhí)行他指定的回調(diào)函數(shù)。如果當(dāng)前代碼耗時很長,有可能要等很久,所以并沒有辦法保證,回調(diào)函數(shù)一定會在setTimeout()指定的是時間執(zhí)行。

Javascript是單線程,單線程就意味著所有任務(wù)需要排隊。然后會將所有任務(wù)分成兩類:同步任務(wù)和異步任務(wù)!同步任務(wù):在主線程上執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完成,才會執(zhí)行后一個!異步任務(wù):不進入主線程、而進入“任務(wù)隊列”的任務(wù)。

Js是單線程的,但是瀏覽器是多線程的!瀏覽器是事件驅(qū)動的!

JS運行在瀏覽器中,是單線程的,每個window一個JS線程,但是瀏覽器不是單線程??赡苡卸鄠€如下線程:

Javascript引擎線程、界面渲染線程、瀏覽器事件觸發(fā)線程、Http請求線程。

setTimeout可以改變,js執(zhí)行順序。比如:我們想要輸出Hello World,world必須在hello之后輸出,不管我們代碼的順序怎么樣都輸出同樣的效果,這個時候就可以借助setTimeout。

//代碼一 var date =  +new Date(); console.log('Hello',new Date()-date); setTimeout(function(){      console.log('world',new Date()-date); },500);  //代碼二: var date =  +new Date(); setTimeout(function(){      console.log('World',new Date()-date); },500); console.log('Hello',new Date()-date);  //以上兩個代碼運行結(jié)果一樣,結(jié)果都是:先輸出Hello ,然后500ms之后輸出World![實際運行:501ms]

瀏覽器中定時器也是一個線程!

Javscript是單線程的,ajax請求確實是異步的!原因是ajax請求的時候,是在瀏覽器的Http請求線程中執(zhí)行的,執(zhí)行之后的回調(diào)函數(shù)會放到Javascript線程中執(zhí)行!

Summary:

Javascript是單線程的,瀏覽器是多線程的,瀏覽器的線程包括:JS引擎線程、界面渲染線程、瀏覽器事件線程、Http請求線程。不過不同的瀏覽器提供的線程是有區(qū)別的。一般JS引擎線程和界面渲染線程是互斥的,兩個線程不能同時執(zhí)行,否則,就會出現(xiàn)界面渲染線程和JS線程修改同一個DOM樣式的矛盾問題!

關(guān)于如何理解JavaScript單線程及setTimeout定時器問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。

分享題目:如何理解JavaScript單線程及setTimeout定時器
分享路徑:http://muchs.cn/article30/gjgeso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設(shè)、網(wǎng)站排名小程序開發(fā)、網(wǎng)站策劃、網(wǎng)頁設(shè)計公司搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)