日期:2014-05-16  浏览次数:20396 次

Javascript学习之一 -- 执行时的准备工工作

?

Javascript执行时的准备工作:

当JS引擎进入一个执行环境,准备执行该区域的代码时,如下工作已经完成:(1) 变量的实例化,(2) 作用域链的创建和初始化,(3) this指针所指向的目标对象的确定。

?

1、执行环境(Execution Contexts

一段可执行的JS代码即为一个执行环境,分为三类:

1.1 全局代码;全局代码是不包含任何函数体的代码(可以有函数调用);

1.2 Eval代码;eval是JS中的一个内置函数,eval的参数即全局代码;

1.3 函数代码;函数代码是函数体中的一部分代码,这部分代码不嵌套包括任何函数体代码。注意new Function(argList)最后一个参数也是当作函数代码处理。

?

?

2、变量实例化(Variable Instantiation?)

?

JS的每个执行环境(也叫执行上下文)都关联到一个变量对象variable object)。变量实例化将做以下事情:

2.1 ?如果该执行环境是函数代码的执行环境,每一个形参作为属性添加到变量对象中,属性名为形参名,值是调用该函数时所提供的实参的值。如果实参少于形参,则多出的形参赋值为undefined。如果有形参中有两个或者两个以上的参数的名字相同,则最后一个形参的值是变量对象中该形参的值,即使最后一个形参为undefined。

?

?

2.2 ?把函数定义式定义的函数(不是函数表达式定义的函数)作为属性添加到变量对象中。属性名为函数名,值为通过new Function(参数列表) 创建的一个函数对象,该对象的属性由代码决定(执行的时候确定)。如果变量对象中已经存在该名字的属性,则用新的值和属性替换旧的值和属性。

?? 如果执行环境是函数代码,必须先初始化函数的形参列表,然后再处理该步骤。

?

?

2.3 把通过关键字var定义的变量(该变量也可以是源码某个语句块中定义的,如:for语句循环体中定义的)作为属性添加到变量对象中,属性名为变量名,值为undefined,值的属性由代码确定(执行的时候确定);如果该变量名和函数定义或者形参重合,则不摈弃变量对象中该属性的已有属性。

?? ? ?语义上,必须先初始化函数形参列表和函数定义,再处理该步骤。

?

?

?

实验1(环境Chrome 8 ):

<script language="javascript">
var fun;
function fun(a, b, a){
	alert(a);
}
fun(1, 2, 3);//弹出:3
fun(1, 2);//弹出:undefined
var fun = 'not function';
fun(1);//出错
</script>

程序解读:
(1) 在执行第2行代码时,全局对象window中已经存在属性window.fun其值为fun函数,而不是一个变量,即使在函数fun前后都有对变量fun的声明,这是因为2.3所述。
(2) 第6行弹出3,第7行弹出undefined,这是因为2.1所述。
(3) 第9行出错是因为执行第8行代码时,改变了window.fun的值(第八行不是变量实例化,而是计算表达式执行代码)。

?

?

3、作用域链(Scope Chain)和变量识别(Identifier Resolution

每个执行环境都与一个作用域链关联。作用域链是一个对象列表,主要用于变量识别(可以理解为它由赋值后的变量对象以链表的形式构成)。系统按照以下步骤来计算一个变量 v的值:

step 1: ?获取作用域链中的下一个对象 ob,如果不存在下一个则转step 3;
step 2: ?调用ob.hasProperty(v),如果结果为true,返回ob.v的引用;如果为false,则转到step 1;
step?3: ?否则返回一个null.v (null是Null的一个对象).

注意:用到作用域链时,说明代码已经开始执行,这时作用域链中各个对象的值已计算得到,例如:变量对象中未确定的属性的值。

4、全局变量(global object)

?

在JS运行环境中存在一个特殊的全局对象,该对象在执行任何代码之前创建。在HTML文档对象模型中全局对象为DOMWindow,