1. 程式人生 > >js同步異步執行順序setTimeOut面試題分析

js同步異步執行順序setTimeOut面試題分析

asc func 運行機制 .html tar target 關系 裏的 等待

    <script>
    for(var i=0;i<2;i++){
      setTimeout(function(){
              console.log(i);
        },0);
    }
    </script>
  //  結果:2,2

打印兩個2而不是0,1,跟js執行順序有關系。

所有的任務分為兩種,一種是同步任務,一種是異步任務。同步任務是指在主線程上排隊的任務。異步任務是指不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務可以執行了,該任務才會進入主線程執行。

(1)所有同步任務都在主線程上執行,形成一個執行棧(execution context stack)。

(2)主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。

(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,於是結束等待狀態,進入執行棧,開始執行。

詳情看阮一峰JavaScript運行機制。鏈接:http://www.ruanyifeng.com/blog/2014/10/event-loop.html

setTimeOut函數為異步任務,for循環為同步任務,setTimeOut裏的函數為回調函數。執行順序為:同步優先,異步靠邊,回調墊底。所以即使setTimeOut的時間參數是0依然會放到任務隊列裏,而不是主線程。主線程執行完for循環以後才執行異步任務setTimeOut。另外setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程才會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等很久,所以並沒有辦法保證,回調函數一定會在setTimeout()指定的時間執行。

<script>
    for(var i=0;i<2;i++){
      (function(){
          console.log(i);
      }(i))
    }
</script>
// 結果:0,1

裏邊換成立即執行函數,則會打印0,1.

js同步異步執行順序setTimeOut面試題分析