最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScrip單線程引擎工作原理分析

 更新時間:2010年09月04日 20:11:53   作者:  
從基礎(chǔ)的層面來講,理解JavaScript的定時器是如何工作的是非常重要的,文章通過講解JavaScript的單線程引擎,從而讓讀者更加深入的了解JavaScript定時器。
從基礎(chǔ)的層面來講,理解JavaScript的定時器是如何工作的是非常重要的。定時器的執(zhí)行常常和我們的直觀想象不同,那是因為JavaScript引擎是單線程的。我們先來認(rèn)識一下下面三個函數(shù)是如何控制計時器的。

腳本之家推薦閱讀:雕蟲無小技 JavaScript初學(xué)者的10個迷你技巧

復(fù)制代碼 代碼如下:

var id = setTimeout(fn, delay);


初始化一個計時器,然后在指定的時間間隔后執(zhí)行。該函數(shù)返回一個唯一的標(biāo)志ID(Number類型),我們可以使用它來取消計時器。
復(fù)制代碼 代碼如下:

var id = setInterval(fn, delay);

和setTimeout有些類似,但它是連續(xù)調(diào)用一個函數(shù)(時間間隔是delay參數(shù))直到它被取消。
復(fù)制代碼 代碼如下:

clearInterval(id);, clearTimeout(id);

使用計時器ID(setTimeout 和 setInterval的返回值)來取消計時器回調(diào)的發(fā)生。

為了理解計時器的內(nèi)在執(zhí)行原理,有一個重要的概念需要加以探討:計時器的延遲(delay)是無法得到保障的。由于所有JavaScript代碼是在一個線程里執(zhí)行的,所有異步事件(例如,鼠標(biāo)點擊和計時器)只有擁有執(zhí)行機(jī)會時才會執(zhí)行。用一個很好的圖表加以說明:

在這個圖表中有許多信息需要理解,如果完全理解了它們,你會對JavaScript引擎如何實現(xiàn)異步事件有一個很好的認(rèn)識。這是一個一維的圖標(biāo):垂直方向表示時間,藍(lán)色的區(qū)塊表示JavaScript代碼執(zhí)行塊。例如第一個JavaScript代碼執(zhí)行塊需要大約18ms,鼠標(biāo)點擊所觸發(fā)的代碼執(zhí)行塊需要11ms等等。

由于JavaScript引擎同一時間只執(zhí)行一條代碼(這是由于JavaScript單線程的性質(zhì)),所以每一個JavaScript代碼執(zhí)行塊會“阻塞”其它異步事件的執(zhí)行。這就意味著當(dāng)一個異步事件發(fā)生(例如,鼠標(biāo)點擊,計時器被觸發(fā),或者Ajax異步請求)后,這些事件的回調(diào)函數(shù)將排在執(zhí)行隊列的最后等待執(zhí)行(實際上,排隊的方式根據(jù)瀏覽器的不同而不同,所以這里只是一個簡化);

從第一個JavaScript執(zhí)行塊開始研究,在第一個執(zhí)行塊中兩個計時器被初始化:一個10ms的setTimeout()和一個10ms的setInterval()。依據(jù)何時何地計時器被初始化(計時器初始化完畢后就會開始計時),計時器實際上會在第一個代碼塊執(zhí)行完畢前被觸發(fā)。但是,計時器上綁定的函數(shù)不會立即執(zhí)行(不被立即執(zhí)行的原因是JavaScript是單線程的)。實際上,被延遲的函數(shù)將依次排在執(zhí)行隊列的最后,等待下一次恰當(dāng)?shù)臅r間再執(zhí)行。

此外,在第一個JavaScript執(zhí)行塊中我們看到了一個“鼠標(biāo)點擊”事件發(fā)生了。一個JavaScript回調(diào)函數(shù)綁定在這個異步事件上了(我們從來不知道用戶什么時候執(zhí)行這個(點擊)事件,因此認(rèn)為它是異步的),這個函數(shù)不會被立即執(zhí)行,和上面的計時器一樣,它將排在執(zhí)行隊列的最后,等待下一次恰當(dāng)?shù)臅r候執(zhí)行。

當(dāng)?shù)谝粋€JavaScript執(zhí)行塊執(zhí)行完畢后,瀏覽器會立即問一個問題:哪個函數(shù)(語句)在等待被執(zhí)行?在這時,一個“鼠標(biāo)點擊事件處理函數(shù)”和一個“計時器回調(diào)函數(shù)”都在等待執(zhí)行。瀏覽器會選擇一個(實際上選擇了“鼠標(biāo)點擊事件的處理函數(shù)”,因為由圖可知它是先進(jìn)隊的)立即執(zhí)行。而“計時器回調(diào)函數(shù)”將等待下次適合的時間執(zhí)行。

注意,當(dāng)“鼠標(biāo)點擊事件處理函數(shù)”執(zhí)行的時候,setInterval的回調(diào)函數(shù)第一次被觸發(fā)了。和setTimeout的回調(diào)函數(shù)一樣,它將排到執(zhí)行隊列的最后等待執(zhí)行。但是,一定要注意這一點:當(dāng)setInterval回調(diào)函數(shù)第二次被觸發(fā)時(此時setTimeout函數(shù)仍在執(zhí)行)setTimeout的第一次觸發(fā)將被拋棄掉。當(dāng)一個很長的代碼塊在執(zhí)行時,可能把所有的setInterval回調(diào)函數(shù)都排在執(zhí)行隊列的后面,代碼塊執(zhí)行完之后,結(jié)果便會是一大串的setInterval回調(diào)函數(shù)等待執(zhí)行,并且這些函數(shù)之間沒有間隔,直到全部完成。所以,瀏覽器傾向于的當(dāng)沒有更多interval的處理函數(shù)在排隊時再將下一個處理函數(shù)排到隊尾(這是由于間隔的問題)。

我們能夠發(fā)現(xiàn),當(dāng)?shù)谌齻€setInterval回調(diào)函數(shù)被觸發(fā)時,之前的setInterval回調(diào)函數(shù)仍在執(zhí)行。這就說明了一個很重要的事實:setInterval不會考慮當(dāng)前正在執(zhí)行什么,而把所有的堵塞的函數(shù)排到隊列尾部。這意味著兩次setInterval回調(diào)函數(shù)之間的時間間隔會被犧牲掉(縮減)。

最后,當(dāng)?shù)诙€setInterval回調(diào)函數(shù)執(zhí)行完畢后,我們可以看到?jīng)]有任何程序等待JavaScript引擎執(zhí)行了。這就意味著瀏覽器現(xiàn)在在等待一個新的異步事件的發(fā)生。在50ms時一個新的setInterval回調(diào)函數(shù)再次被觸發(fā),這時,沒有任何的執(zhí)行塊阻塞它的執(zhí)行了。所以它會立刻被執(zhí)行。讓我們用一個例子來闡明setTimeout和setInterval之間的區(qū)別:

復(fù)制代碼 代碼如下:

setTimeout(function(){
/* Some long block of code... */
setTimeout(arguments.callee, 10);
 }, 10);
 
 setInterval(function(){
/* Some long block of code... */
 }, 10);

setTimeout(function(){
/* Some long block of code... */
setTimeout(arguments.callee, 10);
 }, 10);
 
 setInterval(function(){
/* Some long block of code... */
 }, 10);

這兩句代碼乍一看沒什么差別,但是它們是不同的。setTimeout回調(diào)函數(shù)的執(zhí)行和上一次執(zhí)行之間的間隔至少有10ms(可能會更多,但不會少于10ms),而setInterval的回調(diào)函數(shù)將嘗試每隔10ms執(zhí)行一次,不論上次是否執(zhí)行完畢。

總結(jié)

◆JavaScript引擎是單線程的,強(qiáng)制所有的異步事件排隊等待執(zhí)行;

◆setTimeout和 setInterval在執(zhí)行異步代碼的時候有著根本的不同;

◆如果一個計時器被阻塞而不能立即執(zhí)行,它將延遲執(zhí)行直到下一次可能執(zhí)行的時間點才被執(zhí)行(比期望的時間間隔要長些);

◆如果setInterval回調(diào)函數(shù)的執(zhí)行時間將足夠長(比指定的時間間隔長),它們將連續(xù)執(zhí)行并且彼此之間沒有時間間隔。

上述這些知識點都是非常重要的。了解了JavaScript引擎是如何工作的,尤其是大量的異步事件(連續(xù))發(fā)生時,才能為構(gòu)建高級應(yīng)用程序打好基礎(chǔ)。

原文作者:John Resig

原文鏈接:http://ejohn.org/blog/how-javascript-timers-work/

相關(guān)文章

  • Bootstrap基本組件學(xué)習(xí)筆記之分頁(12)

    Bootstrap基本組件學(xué)習(xí)筆記之分頁(12)

    這篇文章主要為大家詳細(xì)介紹了Bootstrap基本組件學(xué)習(xí)筆記之分頁,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • JavaScript實現(xiàn)下拉菜單的顯示隱藏

    JavaScript實現(xiàn)下拉菜單的顯示隱藏

    這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)下拉菜單的顯示隱藏,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • javascript實現(xiàn)圖片循環(huán)漸顯播放的方法

    javascript實現(xiàn)圖片循環(huán)漸顯播放的方法

    這篇文章主要介紹了javascript實現(xiàn)圖片循環(huán)漸顯播放的方法,涉及javascript操作圖片的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 微信小程序?qū)崿F(xiàn)倒計時補零功能

    微信小程序?qū)崿F(xiàn)倒計時補零功能

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)倒計時補零功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 一文帶你玩轉(zhuǎn)JavaScript的箭頭函數(shù)

    一文帶你玩轉(zhuǎn)JavaScript的箭頭函數(shù)

    在ES6中新增了函數(shù)的簡寫方式----箭頭函數(shù),箭頭函數(shù)的出現(xiàn)不僅簡化了大量代碼,也讓代碼看起來更加優(yōu)雅,同時也解決了this指向問題,下面我們就來詳細(xì)講解如何玩轉(zhuǎn)箭頭函數(shù)
    2022-09-09
  • 如何利用Typescript封裝本地存儲

    如何利用Typescript封裝本地存儲

    這篇文章主要給大家介紹了關(guān)于如何利用Typescript封裝本地存儲的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-01-01
  • js判斷滾動條是否已到頁面最底部或頂部實例

    js判斷滾動條是否已到頁面最底部或頂部實例

    這篇文章主要介紹了js判斷滾動條是否已到頁面最底部或頂部的原理與方法,以實例的形式詳細(xì)分析了js實現(xiàn)返回頂部功能所涉及的各種技巧,并對相關(guān)知識點進(jìn)行了總結(jié)歸納,需要的朋友可以參考下
    2014-11-11
  • js中的內(nèi)部屬性與delete操作符介紹

    js中的內(nèi)部屬性與delete操作符介紹

    這篇文章主要介紹了js中的內(nèi)部屬性與delete操作符的相關(guān)資料,需要的朋友可以參考下
    2015-08-08
  • js實現(xiàn)輪播圖的兩種方式(構(gòu)造函數(shù)、面向?qū)ο?

    js實現(xiàn)輪播圖的兩種方式(構(gòu)造函數(shù)、面向?qū)ο?

    這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)輪播圖的兩種方式,一是構(gòu)造函數(shù)、另一種是面向?qū)ο蠓绞椒绞?,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • javascript css styleFloat和cssFloat

    javascript css styleFloat和cssFloat

    在寫js操作css的過程中發(fā)現(xiàn)float屬性在IE和firefox下對應(yīng)的js腳本是不一樣的,IE下對應(yīng)得是 styleFloat,firefox,chorme,safari下對應(yīng)的是cssFloat,可用in運算符去檢測style是否包含此屬性。
    2010-03-03

最新評論

禹州市| 西充县| 灵璧县| 襄汾县| 鹤峰县| 抚宁县| 郓城县| 大埔区| 铁岭市| 南澳县| 曲靖市| 维西| 明溪县| 井研县| 洛隆县| 玉田县| 乌拉特前旗| 长子县| 安庆市| 南阳市| 宁明县| 潼南县| 忻城县| 靖宇县| 会东县| 景洪市| 石林| 彭水| 海原县| 毕节市| 桦川县| 宁蒗| 胶南市| 康乐县| 璧山县| 呼伦贝尔市| 灵台县| 凤庆县| 揭阳市| 孙吴县| 平江县|