《JavaScript变量对象学习笔记》

        

2017-03-14

在Javascipt中,我们不可避免需要声明变量和函数,我结合自己的理解,记录一下javascript解析器是如何找到这些变量的。


首先,我们先了解一下执行上下文,我们知道,在调用一个函数的时候,就会创建一个新的执行上下文,,而一个执行上下文的生命周期可以分为两个阶段:

1.创建阶段
在这个阶段中,执行上下文会做三件事。第一,创建变量对象,第二,建立作用域链,第三,确定this的指向。

2.执行阶段
创建完成,就会开始执行代码,这个时候也会做三件事,第一,完成变量的赋值,第二,完成函数的引用,第三,执行其他代码


Javascript中执行上下文是以栈的方式存储,我们知道,栈是先进后出。在函数调用栈中,栈底永远是全局环境,栈顶是函数局部环境,那么,我们在调用函数的时候,一定是先等局部执行上下文执行完毕才会轮到全局执行上下文。我们看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var color = "blue";
function changeColor(){
var anothorColor = "red";
function swapColors(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}
swapColors();
}
changeColor();

 
我们来分析一下这个代码的执行过程,首先,是全局上下文入栈,之后可执行代码开始执行,遇到changeColor(),这个时候进入changeColor()函数调用,changeColor()函数执行上下文开始创建,然后changeColor()的函数执行上下文入栈,之后控制器开始执行changeColor()函数内的可执行代码,遇到了swapColors()函数,这个时候进入swapColors()函数调用,swapColors()函数的执行上下文开始创建,然后入栈,之后swapColors()代码顺利执行完毕,swapColors()的上下文先从栈中跳出,之后继续执行changeColor()代码,发现无可执行代码后,changeColor()的函数上下文页从栈中跳出,栈中只剩全局可执行上下文,直到浏览器窗口关闭,至此,全局可执行上下文也从栈中弹出。

 

 下面我们看一下变量对象的有关知识。当我们创建一个变量对象时,需要经历哪写过程呢?  

1.建立arguments对象。
2.检查当前上下文的函数声明。
3.检查当前上下文的变量声明。没找到一个变量声明,就在变量对象中以变量名建立一个属性,值为undefined.

这样,我们可以很轻松的理解变量提升这个概念。直接看一个例子。

1
2
3
4
5
6
7
8
9
10
11
function th(){
console.log(name);
console.log(hello());
var name = "tian";
function hello(){
return 2;
}
}
th();

 对于这个例子,我们可以直接从th()的执行上下文开始理解,当th()被调用的时候,它的执行上下文开始创建,在未执行的时候,变量对象中的属性都不能访问,当开始进入执行阶段,变量对象变为活动对象,里面的属性可以被访问了,这个时候上面的这个例子,执行顺序就变成这样:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function th(){
  function hello(){
return 2;
}
   var name;
console.log(name); //undefined
console.log(hello()); //2
  
   name = "tian";
}
th();