javascript執行環境(執行期上下文)
當js控制器(control)進入可執行代碼時,控制器會進入一個執行環境,活動的多個執行環境構成執行環境棧,最上面的是正在運行的執行環境,當控制器進入一個新的執行環境時,新的執行環境被放到棧最頂端。 執行環境包含以下三個組件: 組件 作用目的 詞法環境 執行環境內的代碼創建的標識符引用的一個詞法環境對象 變量環境 執行環境內的代碼通過變量表達式和函數表達式創建的綁定的一個詞法環境對象。 this綁定 指定該執行環境內的this關鍵字所關聯的值。 執行環境的建立 當執行全局代碼,使用eval函數,執行一個函數時,會創建執行環境。 創建執行環境分兩步,第一步初始化執行環境,下面是全局代碼和函數的初始化過程: 1,全局代碼 ECMA全局執行環境C的初始化過程: (1)將變量環境設置為全局環境 (2)將詞法環境設置為全局環境 (3)將this綁定設置為全局對象 2,進入函數代碼 當進入一個函數對象F,調用者提供的thisArg,調用者提供的argumentsList時,執行以下步驟 (1)設置this: if(函數是嚴格模式代碼){ this=thisArg; }else if(thisArg===null||thisArg=undefined){ this=全局對象 }else if(Type(thisArg!==Object)){ this=ToObject(thisArg); }else{ this=thisArg; } (2)以F的內部屬性[[Scope]]作為參數調用來調用聲明式執行環境,結果記為localEnv, 設置詞法環境為localEnv,設置變量環境為localEnv (3)令code為F的內部屬性[[Code]] 接下來就是聲明綁定初始化過程,此過程比較復雜,主體過程如下: 1,env=當前執行環境的變量環境 2,if(eval代碼){ configurableBindings=true; }else{ configurableBindings=false; } 3,if(strict mode code){ strict=true; }else{ strict=false; } 4,if(函數代碼){ func=調用code的內部屬性[[Call]]的結果 names=func的形式參數[[FormalParameters]]內部屬性 argCount=args的長度 n=0 foreach(argName in names){ n++ v=n>argsCount?undefined:v=args[n] argAlreadyDeclared=env.HasBinding(argName) if(argAlreadyDeclared===false){ env.CreateMutableBinding(argName)//變量環境創建可變綁定 } env.SetMutableBinding(argName,v,strict)//變量環境設置可變綁定 } } 5,對於code中的每一個函數聲明f,按以下步驟進行: fn=f的Identifier fo=f的初始化結果 funcAlreadyDeclared=env.HasBinding(fn) if(funcAlreadyDeclared===false){ env.CreateMutableBinding(fn,configurableBindings) }else if(env===全局環境記錄對象){ go=全局對象 existingProp=以fn為參數調用go的內部屬性[[GetProperty]]的結果 if(existingProp的[[Configurable]]內部屬性===true){ go.[[DefineOwnProperty]](fn,Property Descriptor {[[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true , [[Configurable]]: configurableBindings },true) }else if(existingProp是訪問器屬性描述符 或 existingProp 沒有屬性值{[[Writable]]: true, [[Enumerable]]: true}){ Throw a TypeError exception } env.SetMutableBinding(fn,fo,strict) } 6,argumentsAlreadyDeclared=env.HasBinding(arguments) 7,if(code is function code and argumentsAlreadyDeclared===false){ argsObj=CreateArgumentsObject(func, names, args, env , strict) if(strict===true){ env.CreateImmutableBinding(arguments) env.InitializeImmutableBinding(arguments,argsObj)//嚴格模式的arguments不可變 }else{ env.CreateMutableBinding(arguments) env.SetMutableBinding(arguments,args,false)//非嚴格模式arguments可變 } } 8,對於code中的每一個變量聲明d: dn=d的Identifier varAlreadyDeclared=env.HasBinding(dn) if(varAlreadyDeclared===false){ env.CreateMutableBinding(dn,configurableBindings) env.SetMutableBinding(dn,undefined,strict) }