Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产精品亚洲精品影院,99视频在线观看免费,国产精品亚洲片在线花蝴蝶

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          詳解JavaScript事件循環機制

          詳解JavaScript事件循環機制

          所周知,JavaScript 是一門單線程語言,雖然在 html5 中提出了 Web-Worker ,但這并未改變 JavaScript 是單線程這一核心。可看HTML規范中的這段話:

          To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. There are two kinds of event loops: those for browsing contexts, and those for workers.

          為了協調事件、用戶交互、腳本、UI 渲染和網絡處理等行為,用戶引擎必須使用 event loops。Event Loop 包含兩類:一類是基于 Browsing Context ,一種是基于 Worker ,二者是獨立運行的。 下面本文用一個例子,著重講解下基于 Browsing Context 的事件循環機制。

          來看下面這段 JavaScript 代碼:

           
          setTimeout(function() {
           console.log('setTimeout');
          }, 0);//前端全棧交流學習圈:866109386
          //幫助1-3年前端人員,突破技術,提升思維 
          Promise.resolve().then(function() {
           console.log('promise1');
          }).then(function() {
           console.log('promise2');
          });
           
          console.log('script end');
          

          先猜測一下這段代碼的輸出順序是什么,再去瀏覽器控制臺輸入一下,看看實際輸出的順序和你猜測出的順序是否一致,如果一致,那就說明,你對 JavaScript 的事件循環機制還是有一定了解的,繼續往下看可以鞏固下你的知識;而如果實際輸出的順序和你的猜測不一致,那么本文下面的部分會為你答疑解惑。

          任務隊列

          所有的任務可以分為同步任務和異步任務,同步任務,顧名思義,就是立即執行的任務,同步任務一般會直接進入到主線程中執行;而異步任務,就是異步執行的任務,比如ajax網絡請求,setTimeout 定時函數等都屬于異步任務,異步任務會通過任務隊列( Event Queue )的機制來進行協調。具體的可以用下面的圖來大致說明一下:



          同步和異步任務分別進入不同的執行環境,同步的進入主線程,即主執行棧,異步的進入 Event Queue 。主線程內的任務執行完畢為空,會去 Event Queue 讀取對應的任務,推入主線程執行。 上述過程的不斷重復就是我們說的 Event Loop (事件循環)。

          在事件循環中,每進行一次循環操作稱為tick,通過閱讀規范可知,每一次 tick 的任務處理模型是比較復雜的,其關鍵的步驟可以總結如下:

          • 在此次 tick 中選擇最先進入隊列的任務( oldest task ),如果有則執行(一次)
          • 檢查是否存在 Microtasks ,如果存在則不停地執行,直至清空Microtask Queue
          • 更新 render

          主線程重復執行上述步驟

          可以用一張圖來說明下流程:



          這里相信有人會想問,什么是 microtasks ?規范中規定,task分為兩大類, 分別是 Macro Task (宏任務)和 Micro Task(微任務), 并且每個宏任務結束后, 都要清空所有的微任務,這里的 Macro Task也是我們常說的 task ,有些文章并沒有對其做區分,后面文章中所提及的task皆看做宏任務( macro task)。

          (macro)task 主要包含:script( 整體代碼)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 環境)

          microtask主要包含:Promise、MutaionObserver、process.nextTick(Node.js 環境)

          setTimeout/Promise 等API便是任務源,而進入任務隊列的是由他們指定的具體執行任務。來自不同任務源的任務會進入到不同的任務隊列。其中 setTimeout 與 setInterval 是同源的。

          分析示例代碼

          千言萬語,不如就著例子講來的清楚。下面我們可以按照規范,一步步執行解析下上面的例子,先貼一下例子代碼(免得你往上翻)。

          console.log('script start');
           
          setTimeout(function() {
           console.log('setTimeout');
          }, 0);//前端全棧交流學習圈:866109386
           //幫助1-3年前端人員,提升技術,突破思維
          Promise.resolve().then(function() {
           console.log('promise1');
          }).then(function() {
           console.log('promise2');
          });
           
          console.log('script end');
          

          整體 script 作為第一個宏任務進入主線程,遇到 console.log,輸出 script start

          遇到 setTimeout,其回調函數被分發到宏任務 Event Queue 中

          遇到 Promise,其 then函數被分到到微任務 Event Queue 中,記為 then1,之后又遇到了 then 函數,將其分到微任務 Event Queue 中,記為 then2

          遇到 console.log,輸出 script end

          至此,Event Queue 中存在三個任務,如下表:

          • 執行微任務,首先執行then1,輸出 promise1, 然后執行 then2,輸出 promise2,這樣就清空了所有微任務
          • 執行 setTimeout 任務,輸出 setTimeout 至此,輸出的順序是:script start, script end, promise1, promise2, setTimeout
          • so,你猜對了嗎?

          看看你掌握了沒

          再來一個題目,來做個練習:

          console.log('script start');
           
          setTimeout(function() {
           console.log('timeout1');
          }, 10);
           
          new Promise(resolve=> {
           console.log('promise1');
           resolve();
           setTimeout(()=> console.log('timeout2'), 10);
          }).then(function() {
           console.log('then1')
          })
           
          console.log('script end');
          

          這個題目就稍微有點復雜了,我們再分析下:

          首先,事件循環從宏任務 (macrotask) 隊列開始,最初始,宏任務隊列中,只有一個 scrip t(整體代碼)任務;當遇到任務源 (task source) 時,則會先分發任務到對應的任務隊列中去。所以,就和上面例子類似,首先遇到了console.log,輸出 script start; 接著往下走,遇到 setTimeout 任務源,將其分發到任務隊列中去,記為 timeout1; 接著遇到 promise,new promise 中的代碼立即執行,輸出 promise1, 然后執行 resolve ,遇到 setTimeout ,將其分發到任務隊列中去,記為 timemout2, 將其 then 分發到微任務隊列中去,記為 then1; 接著遇到 console.log 代碼,直接輸出 script end 接著檢查微任務隊列,發現有個 then1 微任務,執行,輸出then1 再檢查微任務隊列,發現已經清空,則開始檢查宏任務隊列,執行 timeout1,輸出 timeout1; 接著執行 timeout2,輸出 timeout2 至此,所有的都隊列都已清空,執行完畢。其輸出的順序依次是:script start, promise1, script end, then1, timeout1, timeout2

          用流程圖看更清晰:



          總結

          有個小 tip:從規范來看,microtask 優先于 task 執行,所以如果有需要優先執行的邏輯,放入microtask 隊列會比 task 更早的被執行。

          最后的最后,記住,JavaScript 是一門單線程語言,異步操作都是放到事件循環隊列里面,等待主執行棧來執行的,并沒有專門的異步執行線程。。

          對前端的技術,架構技術感興趣的同學關注我的頭條號,并在后臺私信發送關鍵字:“前端”即可獲取免費的架構師學習資料

          知識體系已整理好,歡迎免費領取。還有面試視頻分享可以免費獲取。關注我,可以獲得沒有的架構經驗哦!!


          第一節課的時候,我們學過:


          var a=1; //聲明變量
          if(a%2==0){
          console.log(a);
          }
          a=2;
          if(a%2==0){
          console.log(a);
          }
          a=3;
          if(a%2==0){
          console.log(a);
          }
          a=4;
          if(a%2==0){
          console.log(a);
          }

          。。
          a=10
          if(a%2==0){
          console.log(a);
          }

          這是打印10以內的偶數。

          在這個例子的下面,還有幾行語句可以達到相同的效果,但是要精簡很多。

          for(var i=1;i<=10;i++)
          {
          if(i%2==0)
          {
          console.log(i);
          }
          }

          這個for語句就是Javascript的循環語句。

          for語句的語法是這樣的:

          for(初始化語句;條件語句;迭代操作)
          {
          //語句
          }

          在上面的例子中,就是:

          var i=1 這是初始化語句,聲明了一個i的變量,數值是1
          i<=10 條件是i小于等于10
          i++ 就是每次執行循環,i的值自動加1,進行迭代操作。


          下面是例子1

          var count;

          for(count=0;count<=10;count=count+1)
          {
          console.log("Count的值是"+count);
          }

          另外,還有幾種循環語句,這里也一并介紹一下

          1、while語句
          他的語法是:

          while(條件)
          {
          //執行語句
          }


          同樣是執行打印1到10的值,while是這樣的(例子2):

          var count=0;

          while(count<=10)
          {
          console.log("Count的值是"+count);

          count=count+1; //這個地方是必須的,否則count一直為0,就會進入死循環
          }


          2、do..while語句

          它的語法是:

          do {
          //執行語句
          }while(條件)


          同樣打印1到10的值(例子3):

          var count=0;

          do {
          console.log("Count的值是"+count);

          count=count+1; //這個地方是必須的,否則count一直為0,就會進入死循環
          }while(count<=10);


          最后一個例子是綜合第三節的if語句,來一個稍微復雜的應用。


          我們來求一下所有的“水仙花”數。

          在百度百科里面,水仙花數的定義是這樣的:

          水仙花數(Narcissistic number)也被稱為超完全數字不變數(pluperfect digital invariant, PPDI)、自戀數、自冪數、阿姆斯壯數或阿姆斯特朗數(Armstrong number),
          水仙花數是指一個 3 位數,它的每個位上的數字的 3次冪之和等于它本身(例如:1^3 + 5^3+ 3^3=153)。

          下面是具體的例子(例子4):

          var i;
          var j;
          var k;

          for(var i=1;i<=9;i++){
          for(j=1;j<9;j++){
          for(k=1;k<9;k++){
          var real_number=i*100+j*10+k;
          if(i*i*i+j*j*j+k*K*k==real_number){
          console("發現水仙花數:"+real_number);
          }
          }
          }

          }

          今天就到這里。

          avaScript入門教程之循環語句

          循環語句從字面意思理解就是重復執行,能夠讓計算機按照程序員要求重復執行某種操作的能力是所有程序設計語言所必須具備的基本能力。在JavaScript程序設計語言中同樣具有循環語句,實現程序代碼段的重復執行,本文主要從while語句與for語句兩種循環類型方面對循環語句進行說明。


          JavaScript循環語句

          JavaScript為前端程序設計人員提供了三類基本循環控制語句,分別為while語句、do-while 語句與for語句。通過這三種語句程序設計人員可以控制程序重復執行某一操作或者操作的組合。JavaScript基本循環語句執行流程描述如下圖所示:

          JavaScript基本循環流程圖

          通過上圖我們可知,作為循環控制語句需要提供循環執行的入口、循環體與執行大的出口三部分。其中出口至關重要,出口為結束循環的條件,如果設置不好,程序將一直重復執行,并進入死循環狀態。入口我們可以理解為初始條件。出口主要通過判斷條件控制,在上圖中當判斷條件返回值為F時,結束并退出循環。以下我們將分別介紹前文提出的三種類型循環。

          do...while循環

          在很多程序設計語言基礎教程中一般沒有把do...while放到整個循環語句最前面進行介紹,主要原因在于與while相比較使用的頻率相對較低,而且過多介紹可能讓初學者對兩者學習記憶產生混淆。此處我們首先介紹do...while 循環,首先我們給出其工作的流程及原理說明。

          do...while執行流程

          do...while 循環執行過程描述如上圖所示,當開始執行循環控制時,首先執行一次循環體,執行完成進行條件判斷,成立繼續進入循環體執行,否則結束循環。因此可知無論如何都會執行循環體一次。這也是do..while與while語句最大的區別。do...while 語法結構與應用實例如下:

          語法說明及示例

          基本語法與測試案例如上所示,執行完之后可以得到1-100之間奇數的和,其和為2500。chrome瀏覽器測試結果如下:

          求和計算結果

          while循環語句

          理解了do...while循環結構之后,再去理解while相對容易,while語句程序執行流程描述如下圖所示:

          while語句執行流程

          while語句執行流程與循環控制基本流程完全一致,首先判斷條件,條件成立進入循環體,執行完再判斷,直到條件不成立結束循環。while循環語法與示例說明如下:

          語法說明及示例

          for循環

          for循環同樣可以完成循環流程控制功能,其工作過程與原理基本與while一致,只是其語法相對其他兩種較為復雜一點。需要通過三個表達式控制循環,三個表達式分別為初始值、判斷表達式、增長值。for循環基本語法與應用示例如下所示:

          語法說明及示例

          以上針對JavaScript程序設計語言流程控制中的循環操作功能進行了分析與說明,三種控制語句異同也做了解釋,并通過示例編寫了簡單程序進行測試。


          本頭條號長期關注編程資訊分享;編程課程、素材、代碼分享及編程培訓。如果您對以上方面有興趣或代碼錯誤、建議與意見,可以聯系作者,共同探討。更多程序設計相關教程及實例分享,期待大家關注與閱讀!JavaScript基礎教程系列教程鏈接如下:

          JavaScript基礎教程(五)流程控制之條件語句

          JavaScript基礎教程(四)二進制位運算

          JavaScript基礎教程(三)64位浮點數加法運算

          JavaScript基礎教程(二)變量、常量與運算符


          主站蜘蛛池模板: 一区二区三区亚洲| 99在线精品一区二区三区| 中文字幕一区二区三区5566 | 国产午夜精品一区二区三区| 无码人妻精品一区二区三区99仓本| 精品国产日产一区二区三区| 国产成人一区二区三区在线观看| 99久久精品国产免看国产一区| 糖心vlog精品一区二区三区| 国模精品一区二区三区| 亚洲一区二区三区播放在线| 国产伦精品一区三区视频| av无码人妻一区二区三区牛牛 | 亚洲国产一区在线观看| 波多野结衣一区视频在线| 精品黑人一区二区三区| 国产福利一区二区| 日韩a无吗一区二区三区| 国产日韩视频一区| 能在线观看的一区二区三区| 国产精品电影一区二区三区| 国产精品伦子一区二区三区| 国产高清视频一区二区| 高清一区二区三区| 精品福利一区二区三区| 丰满岳乱妇一区二区三区| 日本丰满少妇一区二区三区| 国产精品毛片a∨一区二区三区| 精品亚洲一区二区三区在线观看 | 国产精品免费视频一区| 黑人一区二区三区中文字幕| 亚洲成av人片一区二区三区| 国产福利视频一区二区| 久久99国产精一区二区三区| 91视频一区二区| 日本免费一区尤物| 亚洲国产精品一区二区第一页免 | 在线观看精品一区| 国偷自产视频一区二区久| 精品亚洲一区二区三区在线观看| 一本大道东京热无码一区|