javascript程式碼執行機制簡單介紹
本文將通過一個簡單的程式碼例項介紹一下javascript引擎對程式碼從定義到執行的相關過程,從而加深對作用域作用域鏈等概念的理解。
在閱讀本文之前最好參閱以下幾篇文章:
(1).執行上下文可以參閱javascript執行上下文詳解一章節。
(2).變數物件可以參閱javascript變數物件詳解一章節。
(3).作用域和作用域鏈可以參閱javascript 作用域和作用域鏈詳解一章節。
以下面的程式碼為例子做一下介紹:
[JavaScript] 純文字檢視 複製程式碼var x = 1;//定義全域性變數x,並賦值為1 function wrap(y){//定義一個全域性函式 var x = 2;//定義一個區域性變數,並賦值為2 function inner(z){//定義一個區域性函式 console.log(x+y+z);//輸出值 } return inner;//返回內部函式 } var f = wrap(3);//將返回的內部函式賦值給變數f f(1);//呼叫函式
上面的程式碼是一個典型的閉包的引用,關於閉包可以參閱javascript閉包概念介紹一章節。
第一階段:
首先會建立一個全域性物件,它的屬性或者方法可訪問性也是全域性的。
全域性物件具有唯一性,並且生命週期會伴隨整個應用程式。
全域性物件建立時,Math,String,Date和document等物件作為其屬性存在。
全域性物件通常只能夠使用別名來訪問,比如在web中就是用window來訪問全域性物件,可以用虛擬碼表示如下:
[JavaScript] 純文字檢視 複製程式碼//建立一個全域性物件 var global = { Math:{}, String:{}, Date:{}, document:{}, //其他屬性 window:this }
這個時候,javascript還會構建一個執行環境棧( Execution Context Stack) 。
與此同時,全域性執行環境上下文Execution Context(EC)也會被建立,並將其壓入執行環境棧中。
執行環境棧的建立目的是為了保證程式碼能夠按照正確的順序執行。
全域性執行環境上下文中還會生一個變數物件(Varibale Object) VO,並把VO指向全域性物件。
VO包含全域性物件中固有的一些屬性,比如Math,String,Date和document等,也包含自定義的函式或者變數。
函式在宣告的同時為其建立一個[[Scope]]內部屬性,表示如下:
[JavaScript] 純文字檢視 複製程式碼wrap.[[Scope]] = [ globalContext.VO ];
此時執行環境棧可以用虛擬碼表示如下:
[JavaScript] 純文字檢視 複製程式碼ECStack = [ //執行環境棧 EC(G) = { //全域性執行環境上下文 VO(G):{ //全域性變數物件 ... //包含全域性物件原有的屬性 x = 1; //定義變數x wrap = function(){}; //定義函式wrap A[[scope]] = [globalContext.VO]; } } ];
第二階段:
當呼叫wrap()函式之後,會建立一個函式執行上下文,並將這個執行上下文壓入執行環境棧的頂部。
此時執行環境棧中有兩個執行環境上下文,分別是全域性執行環境上下文和函式wrap執行環境上下文。
wrap的執行環境上下文在棧頂,全域性執行環境上下文在棧的底部。
函式執行上下文中也會建立變數物件(Varibale Object) VO,不過函式的變數物件通常稱之為活動物件(Activation Object) A0。活動物件A0包含函式的形參、arguments物件、this物件、以及區域性變數和內部函式的定義。
當執行環境上下文被建立時 ,函式wrap的作用域鏈(Scope Chain)就會被建立 ,用於識別符號解析。
作用域鏈(Scope Chain)= 當前VO+A[[scope]]。
此時的ECStack結構:
[JavaScript] 純文字檢視 複製程式碼ECStack = [ //執行環境棧 EC(wrap) = { //A的執行環境 [scope]:VO(G), //VO是全域性變數物件 AO(wrap) : { //建立函式wrap的活動物件 y:3, x:2, //定義區域性變數x inner:function(){}, //定義函式B A[[scope]]:[globalContext.VO]; arguments:[],//在函式中訪問的arguments就是AO中的arguments this:window }, scopeChain:[ wrapContext.AO,//wrap函式變數物件 globalContext.VO//全域性變數物件 ] }, EC(G) = { //全域性執行環境上下文 VO(G):{ //全域性變數物件 ... //包含全域性物件原有的屬性 x = 1; //定義變數x wrap = function(){}; //定義函式wrap A[[scope]] = [globalContext.VO]; } } ];
對於內部函式執行也是同樣的道理,這裡就不多介紹了。
相關文章
- javascript執行順序簡單介紹JavaScript
- js程式碼執行順序簡單介紹JS
- javascript程式碼規範簡單介紹JavaScript
- JavaScript的程式碼執行機制JavaScript
- javascript程式碼效能優化簡單介紹JavaScript優化
- javascript事件控制程式碼簡單介紹JavaScript事件
- 如何除錯javascript程式碼簡單介紹除錯JavaScript
- JavaScript 簡單介紹JavaScript
- 簡單介紹克隆 JavaScriptJavaScript
- javascript物件簡單介紹JavaScript物件
- javascript this指向簡單介紹JavaScript
- javascript加密簡單介紹JavaScript加密
- 簡單介紹python的垃圾回收機制Python
- JavaScript 模組化程式設計簡單介紹JavaScript程式設計
- JavaScript執行機制JavaScript
- Javascript 執行機制JavaScript
- animate動畫連續執行簡單介紹動畫
- 簡單介紹JavaScript閉包JavaScript
- JavaScript希爾排序簡單介紹JavaScript排序
- javascript constructor簡單介紹JavaScriptStruct
- javascript建立物件簡單介紹JavaScript物件
- javascript的this用法簡單介紹JavaScript
- javascript arguments用法簡單介紹JavaScript
- javascript 變數簡單介紹JavaScript變數
- javascript簡單模板引擎介紹JavaScript
- javascript作用域簡單介紹JavaScript
- SVG程式碼構成簡單介紹SVG
- 【多執行緒系列】CAS、AQS簡單介紹執行緒AQS
- jQuery ajax的執行順序簡單介紹jQuery
- 探索JavaScript執行機制JavaScript
- ART執行時垃圾收集機制簡要介紹和學習計劃
- JavaScript return語句簡單介紹JavaScript
- javascript鏈式呼叫簡單介紹JavaScript
- javascript除法運算簡單介紹JavaScript
- javascript &&和||運算子簡單介紹JavaScript
- javascript方法過載簡單介紹JavaScript
- javascript遞迴概念簡單介紹JavaScript遞迴
- JavaScript this指向解綁簡單介紹JavaScript