Javascript基礎語法學習介紹4_Function運行原理_Hosting、Scope與 ScopeChain觀念
我們於之前這篇
有簡單介紹function語法使用
但是那時還來不及詳細解說其中原理
Function運行原理
Function 之定義&調用示例
1 2 3 4 5 6 7 8 9 10 11 | //沒有參數的function function myFunc(){ console.log('This is no parameter function'); } myFunc(); //有參數的function function sum(a,b){ var c = a+b; console.log(c); } sum(3,4); |
每一個function於程式運行中途跑到該區function定義區域時
會自動建立一塊Execution Context之後
於function內部其實還會有兩階段過程運作
【Function 建立階段】
=>Stage1-1.初始化一個空間(Scope Chain)
=>Stage1-2.創建三種變數物件 VO (Variable Object)
第一種 function arguments object(參數物件)
第二種 function中的function之指標 object
第三種 function中的變數設值為undifined
1 2 3 4 | function 函式名稱(參數物件){ 掃描function中的function - pointer 掃描function中的variable - 設為undifined } |
=>Stage1-3.決定 this variable 的 值
【Function 運行階段】
=>進行逐行運行
======================================================================
這邊來一個簡單範例
1 2 3 4 5 6 7 8 9 10 11 | function myFunc(i){ var a = 'Hi'; var b = function innerFunc(){ }; function c(){ } } myFunc(7); |
Step1.創建(先掃描)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //當function運行時 //會建立 execution Context 之後於function內部做創建 /* myFunc_Execution_Context = { scopeChain: {....}, //Stage1-1.初始化空間(範圍鏈) //Stage1-2.創建變數物件 variableObj:{ //第一種VO:arguments object(參數物件) arguments:{ 0:7, length: 1 } i:22, //第二種 function中的function之指標 object c:pointer to function c() //第三種 function中的變數設值為undifined b:undifined, a:undifined } } */ |
Step2.運行(值真正傳入)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* //運行階段 myFunc_Execution_Context = { scopeChain: {....}, //Stage2-1.初始化空間(範圍鏈) //Stage2-2.變數物件值傳入 variableObj:{ 0:7, length: 1 } i:22, c:pointer to function c(), b:pointer to function innerFunc(), a:'Hi' } */ |
Hosting效應
正常Case1: 先定義後調用
特殊Case1: 先調用後定義
所以解析器早已在function建立時就知道function的存在了
緊接著再來看一個示例
正常Case2: 先定義後調用
特殊Case2: 先調用後定義
诶~~ 這裡會覺得納悶為何會出現錯誤
主要錯誤訊息再於Hosting效應只適用於function型態的宣告情況
不適用於將function指派於變數之陳述式情況
我們在上面兩case之所以都能正常運行
主要是因為是作為 function型態的呼叫
於這邊我們用變數來存放所以預設都會給予undefined!!!!
概念和下方是一樣的
這裡可以看到變數一開始尚未被解析器讀取到內容預設所給予的是undefined
下方還有一個例子
你會看到 myFunc我們自定義的函數會先調用對應區域變數輸出age=35
之後外部範圍讀取到的則為全域內容age=24
Scope與 ScopeChain觀念
一段JS code 於運行過程時會先建立Global Scope包含所有最上面定義
之變數或物件內容所以又可稱為Global Variale Object
之後每執行下去到特定區域就會包含Global Scope的內容可以去調用
當然first()函數中由於再內部呼叫second()之前已先有定義b變數值
所以也會傳入到second()區塊中
所以下方程式區塊共會切分開三個scope
Global Scope
first() function scope : 包含Global Scope 和first函數內部自己定義的VO
second() function scope : 包含Global Scope 、first函數內部定義的VO、自己second()的VO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //====================Scope / Scope-Chain============= //Global Scope (Global Variable Object) //========================================= var a = 'Hello'; first(); //========================================= //first() function scope (variable object_1) + (Global Variable Object) function first(){ var b = 'Hi'; second(); //secod() function scope (variable object_1)+(variable object_2) + (Global Variable Object) function second(){ var c = 'Hey'; console.log(a+b+c); } } |
所謂的Scope就是我們俗稱的作用範圍
我們說全域區塊(外圍)有自己的Global Scope
那各自函式中也有自己的Local Scope
你可以在Local Scope中去調用 Global Scope的內容
或是 內部子函式Scope可以調用上一層的Local Scope(只要有包含在其中)
所以連著一系列Scope一條鍊條就形成了 Scope Chain
如下再來一範例
主要可以去觀察所謂ScopeChain有包含的Scope在不同地方呼叫的限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //Global Scope (Global Variable Object) //========================================= var a = 'Hello'; first(); //========================================= //first() function scope (variable object_1) + (Global Variable Object) function first(){ var b = 'Hi'; second(); //secod() function scope (variable object_1)+(variable object_2) + (Global Variable Object) function second(){ var c = 'Hey'; third(); } } function third(){ var d = 'Jimmy'; console.log(a+b+c+d); //console.log(a+d); } |
這段程式碼會有錯誤無法運行輸出
其Scope Chain 只包含
Global Scope
Global Variable Object: a = 'Hello'
Local Scope
Local Variable Object: d = 'Jimmy'
而不包含 first() Scope 及 second() 所以
若將其改成輸出a+d
去除 b 跟 c 則可正常運行
以上是所謂的 Scope與 ScopeChain觀念
留言
張貼留言