JavaScript的異步執行的運行機制和setTimeout的雙重求值


小生現在還是一名大三學生,本專業是工程管理,因為喜歡前端,從大二開始自學,大二上中期加入學院一個前端工作室。工作室從大三開始每周會有一次技術的分享(大三的會講講深一點的JavaScript和css知識,大二會把自己平時學習的體會心得拿出來講),有一次我在講到JavaScript的異步執行的運行機制,使用setTimeout來做的例子。

首先寫一小段代碼:

setTimeout(  function () { console.log(1); } , 1000);

setTimeout(  function () { console.log(2); } , 800);

setTimeout(  function () { console.log(3); } , 600);

明白異步執行的,相信大家都知道打印的順序吧


 

 

 

 

 

 

 

 

 

 

 

具體來說,異步執行的運行機制如下:

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

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

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

(4)主線程不斷重復上面的第三步。

 

根據每個函數的設置的時間,第三個函數最先進入任務隊列,第二個函數第二,第一個函數最后進入。所以彈出3 2 1.

 

但是又有一種情況:

 

setTimeout(  console.log(1) , 1000);

setTimeout(  console.log(2) , 800);

setTimeout(  console.log(3) , 600);

 

這里涉及到另外一個問題:回調函數

"任務隊列"中的事件,除了IO設備的事件以外,還包括一些用戶產生的事件(比如鼠標點擊、頁面滾動等等)。只要指定過回調函數,這些事件發生時就會進入"任務隊列",等待主線程讀取。

所謂"回調函數"(callback),就是那些會被主線程掛起來的代碼。異步任務必須指定回調函數,當主線程開始執行異步任務,就是執行對應的回調函數。

console.log(1) ,console.log(2),console.log(3)並不是構成回調函數,所以它們根本沒有進入任務隊列:而是按照正常的順序在執行棧中被執行了。

 

第二種情況是我在講的時候,下面一位聽講的同學在自己電腦控制台執行出來的。當時問題沒有的到解決,后來我再去搜了一些資料。后面一次分享會,把自認為准確的答案給大家講了,一位問題就這么解決了。沒想到又有一個問題拋出來,把console.log(1) ,console.log(2),console.log(3)各自都加上引號就可以像第一個情況那樣運行。

這時的我又蒙了,分享會完之后我就馬上去查了資料,可是做了無用功,並沒有找到答案,后來在看一本JavaScript的書時,找到了答案。就是標題所說的雙重求值

 

JavaScript像其他其他語言一樣,允許在程序中提取一個包含代碼的字符串,然后動態執行。有四種表中方法可以實現:eval()、Function()構造函數、setTimeout()和setInterval()

var num=1,num2;

//eval()執行代碼字符串

sum = eval("num1 + num2");

//Function()構造函數執行代碼字符串

sum=Function("num1","num2","return num1 +num 2");

//setTimeout()執行代碼字符串

setTimeout("sum=num1 +num2",100);

//setInterval()執行代碼字符串

 

現在問題終於都解決了~~這以前都是些知識點類隨筆,這是我第一次寫學習總結類的隨筆。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM