JavaScript中有三种运行环境
全局环境:JavaScript最开始运行的默认环境
函数环境:函数执行时,函数内的环境
Eval环境:eval()运行环境,不建议使用
JavaScript引擎遇到可执行的程序(以函数为例),会为这段程序创建一个执行上下文(Execution context,EC),执行上下文暂时理解为当前程序的执行环境。每遇到不同的程序(函数),就会为该程序创建一个执行上下文。这些执行上下文就构成一个执行上下文栈(Execution context stack,ECS)。
例1:
var a = "globalVar";
function outerFunc(){
var b = "outerVar";
function innerFunc(){
var c = "innerVar";
}
innerFunc();
}
outerFunc()
程序执行先进入GlobalEC,GlobalEC入栈;然后进入outerFuncEC,outerFuncEC入栈;最后进入innerFuncEC,innerFuncEC入栈。然后程序执行,innerFunc执行完,innerFuncEC出栈;outerFunc执行完,outerFuncEC出栈;程序执行完,GlobalEC出栈。
每一段程序的执行可以分为两个阶段,执行上下文阶段和程序执行阶段。
执行上下文:又叫做程序准备阶段,该阶段创建变量对象、建立作用域链、确定This指向三件事。
程序执行:执行代码,参数赋值,函数引用,变量赋值等。
变量对象
变量对象是和上下文相关的特殊对象,存储着上下文中的相关数据,以属性/值的方式存储三类数据:
参数对象声明:即arguments对象;参数名作为参数对象属性,属性值默认为undefined。
函数声明:函数名作为属性,函数引用作为属性值;若存在同名属性,覆盖原属性值。
变量声明:变量名作为属性,undefined作为属性值;若存在同名属性(参数属性或者函数属性),不影响原属性值。
变量对象是在执行上下文阶段创建的,将上下文中的相关数据(参数、函数、变量)以一定的规则提升到函数内顶级范围并赋值为默认值,这也就是为什么会存在“变量提升”的概念。
例2:
alert(x); //function
var x=10;
alert(x); //10
x=20;
function x(){};
alert(x); //20
程序进入执行上下文阶段:创建VO,因为变量和函数名一样,保持函数名,即VO只有一个属性:VO = {x:< x reference >},该阶段结束。程序进入执行阶段:第一个alert弹出“function x(){}”,因为x默认为函数x;第二个alert弹出“10”,因为在程序执行阶段对x的值进行了修改(这里明确一点:执行上下文阶段 和 程序执行阶段是两个独立的阶段,虽然都是同一个对象(VO > AO),执行阶段仍然会修改对象的值),同样,第三个alert弹出“20”。
例3:
if(true){
var a=1;
}else{
var b=2;
}
alert(a); //1
alert(b); //undefined
例4:
alert(a); //undefined
alert(b); //error:"b"没有定义
b = 10;
var a = 20;
网友评论