js 非同步執行 js執行過程你了解多少?

2021-10-11 04:17:41 字數 3932 閱讀 6025

js執行過程你了解多少? - 重慶崽兒brand的個人主頁​www.brandhuang.com

js是單執行緒語言:

在瀏覽器中只有乙個執行緒在執行js指令碼**。
雖然js是單執行緒,但在js執行過程中並不是只有乙個執行緒。其實有四個執行緒,包括:「js引擎執行緒」「事件觸發執行緒」「定時器觸發執行緒」「http非同步請求執行緒」,但永遠只有「js引擎執行緒」在執行js指令碼,其他三個只是協助,不參與指令碼解析和執行。

js是單執行緒,但是**確是非同步執行的

通過事件迴圈(event loop)的方式實現。
js引擎執行分三個階段

注:瀏覽器首先按順序載入由標籤分割的js**塊,載入js**塊完畢後,立刻進入以下三個階段,然後再按順序查詢下乙個**塊,再繼續執行以下三個階段,無論是外部指令碼檔案(不非同步載入)還是內部指令碼**塊,都是一樣的原理,並且都在同乙個全域性作用域中。
語法分析

預編譯階段

執行階段

分析指令碼**塊語法是否正確,正確則進入「預編譯階段」,否則丟擲syntaxerror, 停止該**塊**繼續執行,然後繼續查詢下乙個**塊。

js的執行環境(執行上下文)主要有三種: - 全域性環境(js**載入完畢後,進入預編譯階段即進入了全域性環境) - 函式環境(函式執行時進入該函式環境,不同函式的函式環境不同) - eval環境(不建議使用,會有安全,效能等問題)

執行棧,又稱呼叫棧,用來存貯**執行期間建立的所有執行上下文。是乙個遵循後進先出(lifo)的結構。棧底永遠是全域性執行上下文,棧頂是當前執行上下文。

執行上下文分兩個階段建立:1)建立執行上下文; 2)執行階段

建立變數物件

建立作用域鏈

確定this指向

主要過程如下:

建立augments物件:檢查當前上下文中的引數,建立物件的屬性與值,僅在函式環境(非箭頭函式?)執行,全域性環境沒有這個過程。

檢查funchtion函式宣告,建立屬性:按**順序查詢,將找到的函式提前宣告,若函式不存在則新建立屬性和屬性值(指向該函式記憶體位址的引用);若存在,則直接覆蓋原來的。

檢查var變數,宣告建立屬性:按**順序查詢,將找到的變數提前宣告,如果變數不存在,則賦值為:undefined。若存在,則忽略該宣告。

注:在全域性環境中,window物件就是全域性執行上下文的變數物件,所有的變數和函式都是window物件的屬性方法。
所以函式宣告提前和變數宣告提公升是在建立變數物件中進行的,且函式宣告優先順序高於變數宣告。

變數提公升:在建立階段,函式宣告儲存在環境中,而變數會被設定為undefined(在var的情況下)或保持未初始化(在letconst的情況下)。所以這就是為什麼可以在宣告之前訪問var定義的變數(儘管是undefined),但如果在宣告之前訪問letconst定義的變數就會提示引用錯誤的原因。

「變數物件」轉化為「活動物件」後才能進行訪問

作用域鏈由當前執行環境的變數物件和上層的一系列活動物件組成,保證了當前執行環境對符合訪問許可權的變數和函式的有序訪問。

例:

var num = 30;

function test()

innertest()

}test()

在上面的例子中,當執行到呼叫innertest函式,進入innertest函式環境。全域性執行上下文和test函式執行上下文已進入執行階段,innertest函式執行上下文在預編譯階段建立變數物件,所以他們的活動物件和變數物件分別是ao(global)ao(test)vo(innertest),而innertest的作用域鏈由當前執行環境的變數物件(未進入執行階段前)與上層環境的一系列活動物件組成,如下:

innertestec = , 

//作用域鏈

scopechain: [vo(innertest), ao(test), ao(global)],

//this指向

this: window

}

全域性環境下指向window

函式環境下需根據執行環境和執行方法確定(==後續補充==)

js進入執行階段後,**執行順序如下:

巨集任務(同步任務) --> 微任務 --> 巨集任務(非同步任務)

1.巨集任務:巨集任務又按執行順序分為同步任務和非同步任務

理解巨集任務中同步任務和非同步任務的執行順序,那麼就相當於理解了js非同步執行機制–事件迴圈(event loop

事件迴圈可以理解為由三部分組成:主線程執行棧非同步任務等待觸發、**任務佇列

在js引擎主線程執行過程中:

首先執行巨集任務的同步任務,在主線程上形成乙個執行棧,可理解為函式呼叫棧;

當執行棧中的函式呼叫到一些非同步執行的api(例如非同步ajaxdom事件,settimeoutapi),則會開啟對應的執行緒(http非同步請求執行緒,事件觸發執行緒和定時器觸發執行緒)進行監控和控制

當非同步任務的事件滿足觸發條件時,對應的執行緒則會把該事件的處理函式推進任務佇列(task queue)中,等待主線程讀取執行

當js引擎主線程上的任務執行完畢,則會讀取任務佇列中的事件,將任務佇列中的事件任務推進主線程中,按任務佇列順序執行

當js引擎主線程上的任務執行完畢後,則會再次讀取任務佇列中的事件任務,如此迴圈,這就是事件迴圈(event loop)的過程

2.微任務:是在es6node環境**現的乙個任務型別.

微任務的api主要有:promiseprocess.nexttick
示例:

console.log('script start');

settimeout(function() , 0);

promise.resolve().then(function() ).then(function() );

console.log('script end');

輸出結果:

script start

script end

promise1

promise2

settimeout

以上就是js執行的過程

你了解JS執行過程嗎?

正如我們了解的一樣,當我們書寫了js程式之後,開啟瀏覽器,我們的 就可以開始執行了 當然保證你的 沒有問題,才能按照你的預期進行執行 剛才說的是js執行的乙個大的環境,今天我們學習一下,js在解析器裡的乙個執行過程。這個過程分為兩個階段 變數物件的變化,和這兩個階段息息相關。在介紹這兩個階段之前,了...

js執行過程

執行過程 1.宿主環境 瀏覽器 把一段 給js引擎 js引擎按順序執行 因為是宿主環境發起,這也是一條巨集任務 2.需要知道每個巨集觀任務尾部會跟著微任務佇列 當有微觀任務出現,會把他放在微任務佇列中,在上一步的巨集任務執行完後再執行 3.若有巨集觀任務出現,會放入巨集觀任務佇列中,等待上一步微任務...

js 函式執行過程

函式執行過程中 1.每使用乙個變數,函式都會由近到遠的遍歷自己的好友列表中的作用域物件。2.如果在離自己近的格仔中找到了區域性變數,就優先使用區域性變數,不再去全域性找。3.如果在離自己近的格仔中沒找到要用的區域性變數,才被迫去全域性找,如果在全域性找到了想用的變數,則本次修改結果,會影響全部變數的...