javascript执行环境(执行期上下文)详解
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) }