”js是一門單執行緒的語言,js最大的特性是非同步“,這些說法已經見慣不怪了,然而不瞭解js的解釋執行始末,這些概念也就只是聽聽,真正遇到問題的時候,也只能一臉懵逼而已~
一、Event Loop 機制/非同步原理
由於 Js 是一門單執行緒的語言,為了實現非同步特性,必須有一種行之有效的機制,Event Loop 就是這種機制
說 Js 是一門單執行緒語言,指的是它只有一個使用者執行執行緒,同一時刻只能執行一個任務,在你看不見的地方,還需要有很多其它執行緒/程式來排程
同步的情況
當程式開始執行的時候,將預設執行全域性執行上下文(將在後文中說明)中的程式碼,如果遇到同步函式,那麼將把當前執行上下文壓入棧中,進入同步函式的執行上下文執行(倘若在函式中又遇到了其它同步函式,將持續此過程),當函式執行完成,執行執行緒將從訊息執行緒中pop一個執行上下文進行執行
global() {
/**
* 定義
*/
EC3() {
}
EC2() {
EC3(); //呼叫EC3
}
EC1() {
EC2();//呼叫EC2
}
//呼叫EC1
EC1();
}複製程式碼
非同步的情況
如果當前執行上下文遇到了非同步操作,那麼它向事件監聽執行緒或者計時執行緒發出通知之後,將繼續執行,此時有兩種情況:
a) 計時函式,如:
setTimeout(func, 1000);複製程式碼
此時,非同步通知將發給計時執行緒(Timer),一秒後,計時執行緒將會把 func
函式的執行上下文壓入訊息執行緒堆疊,執行執行緒在處理完當前執行上下文的時候從訊息執行緒堆疊中 Pop 出 func 的執行上下文進行執行(如果在此期間沒有別的執行上下文入棧的話)
所以,
setTime(func, n);
並不能保證,在 n 毫秒之後 func 能被執行,這還得看執行執行緒當前在幹什麼了
b) 事件監聽執行緒,如果發起的是一個非同步io操作,如發起一個網路請求:
$.ajax(url, params, callback);複製程式碼
那麼非同步事件將發給事件監聽執行緒去監聽,一旦網路請求完成,同樣的,事件監聽執行緒將把 callback 的執行上下文入棧,等待執行執行緒的召喚
二、js的執行上下文
上文反覆提到執行上下文,下面就對執行上下文進行一個深入剖析
如何理解執行上下文
所謂執行上下文,就是 Js 執行的時候的一個執行環境/作用域(scope),有如下幾種情況:
- 全域性執行上下文/作用域:js程式碼的預設執行環境(只有一個)
- 函式執行上下文/作用域:每個函式對應的執行環境(無限多個)
- eval 程式碼執行上下文:使用 eval 執行的腳步的執行環境
/**
* 全域性執行上下文/作用域
*/
console.log('在全域性環境中執行')
function hello() { //hello函式執行上下文/作用域
var say = 'hello';
function world() { //world函式執行上下文
...
}
}複製程式碼
全域性作用域中的方法、變數,可以被其它任何函式作用域所訪問,函式作用域中的方法變數,在子函式作用域中可以訪問,外部無法直接訪問
通過函式返回的子函式去訪問函式作用域的私有變數,也就形成了閉包
執行堆疊
也就是上文提到的 Event Loop,該執行緒以棧的形式儲存執行上下文,函式執行上下文的入棧出棧的過程,使得js得以在單執行緒的情況下,實現非同步特性
執行上下文的建立與執行
每一次函式被呼叫,js直譯器都會為之建立新的上下文,此時可以分為兩個階段:
a) 上下文的建立階段:函式被呼叫,但尚未開始執行(程式碼分析預處理階段),此時會為執行上下文建立作用域鏈,建立變數、函式和引數以及求this的值
executionContextObj = {
scopeChain: { /* 變數物件(variableObject)+ 所有父執行上下文的變數物件*/ },
variableObject: { /*函式 arguments/引數,內部變數和函式宣告 */ },
this: {}
}複製程式碼
特別的,變數提升就是在這個階段發生的
b) 執行階段:指派變數的值和函式的引用並解釋執行程式碼
下面再用虛擬碼的形式來描述一下這個過程:
//函式被呼叫
1. 建立執行上下文
a) 建立作用域鏈
b) 建立變數、函式和引數
c) 求this值
2. 開始執行在執行上下文上 執行
...
a) 遇到同步函式
b) 當前執行上下文入棧
c) 重複以上過程
...
3. 執行完成,往上一層 執行上下文 返回資料
4. 從執行上下文棧pop出一個新的執行上下文執行複製程式碼
二、總結
瞭解 Js 直譯器一些底層原理,是非常有必要的,當程式的執行結果跟你的預期結果不一樣的時候,甚至看起來很詭異的時候,如何去解釋,就很體現能力了
更多精彩,邀您關注~~