(原文出自以下地址:http://www.w3cgroup.com/article.asp?id=293)
ECMA-262简述
ECMAScript语言概述
ECMAScript对象概述(原型链Prototype Chain)
ECMA-262主要术语
ECMAScript执行环境(作用域链Scope Chain,闭包机制)
ECMAScript函数(new原理)
ECMAScript内部属性(参考)
ECMAScript执行环境作用域链图示
ECMA-262参考资料
所有遵循ECMA-262标准实现的脚本都可以称之为ECMAScript,如JavaScript, JScript, ActionScript等等。
脚本语言与宿主环境是两个不同的主体,比如,浏览器就为ECMAScript提供了一个宿主环境,BOM和DOM则都是浏览器提供的功能,而各种基于ECMA262实现的脚本语言,如JavaScript,Jscript等,都可以为我们提供对BOM和DOM的操作方法。因为宿主环境的不同,它们提供的功能也不尽相同,这也是我们知道的,不同的浏览器中会有不同的BOM和DOM的属性和方法。
原始值属于下列“内置类型”(built-in types)中的一员:Undefined, Null, Boolean, Number和String,“对象 ”则是内置类型:Object,“方法”是一个透过property关联到对象的函数。
例如,Cfp是cf3的原型(虚线,表示隐含的原型关系),构造函数CF自己有两个属性P1和P2,它们对 Cfp,cf1,cf2,cf3,cf4,cf5都不可见。Cfp的属性CFP1对cf1,cf2,cf3,cf4,cf5可见(但不包括CF),还有那些在Cfp的隐含的原型链中找到的 property name(非q1,q2或者CFP1的其他属性)。注意,CF和Cfp之间并非隐含的原型联系。
数据值的集合
原始值包括Undefined,Null,Boolean,Number,String这些类型成员。原始值是语言实现中底层可以直接表示的数据。
每个对象都是Object类型的成员。它包含的所有属性成员,如原始值、对象或者函数,是一个无序的集合。对象属性成员放置的函数又被称为方法。
构造器是一个函数对象,用来创建和初始化对象。每个构造器都有一个关联的原型对象用来实现属性成员的继承和共享。
ECMAScript中的原型用来实现对象结构、状态和行为的继承。当一个构造器构造了一个对象,这个对象会隐含地引用到该构造器关联的原型去解析属性的引用。构造器关联的原型可以通过程序表达式constructor.prototype 来引用。在某个共享对象的原型上添加的属性值,通过继承,可以被所有其他对象共享。
原生对象是由ECMAScript的实现提供的,独立于宿主环境。有些原生对像同时又是内置对象,其他的则可能会在执行一个 ECMAScript程序时产生。
内置对象是由ECMAScript的实现提供的,独立于宿主环境,它们出现在ECMAScript程序开始执行的时候。所有的内置对象都是原生对象。
宿主对象由为ECMAScript提供完整执行环境的宿主环境提供的。任何对象,不是原生对象,就是宿主对象。
Undefined值是一个原始值,当一个变量没有被分配值的时候使用。
Undefined类型只有一个值,undefined。
Null值是一个原始值,它表示空的,没有的,或不存在的引用。
Null类型有一个值,null。
Boolean值是Boolean类型的成员,它只能是两个值中的一个,true或false。
Boolean类型表示一个逻辑实体,由两个唯一值组成,一个是true,另一个是false。
Boolean对象是Object类型的成员,它是内置对象Boolean的实例。意思是,一个Boolean对象是通过Boolean构造器的 new表 达式创建,提供一个boolean参数。结果对象有一个隐含的(未命名)原型boolean。一个Boolean对象支配一个 Boolean值。
String值是String类型的成员,它是一个有限的有序的,0到16位无符号整数长度的值。注意:尽管每个值通常都表示一个单独的16位的UTF-16文本的单元,但该语言不会做出任何限制和要求当这个值不是16位无符号整数的情况时。
String类型是所有字符串值的集合。
String对象是Object类型的成员,它是内置对象String的实例。
Number值是Number类型的成员,它是一个直接表示的数字。
Number类型是表示数字的值的集合。在ECMAScript中,该集合表示IEEE754的64位双精度运算格式的值,包含一个特殊值”Not-a- Number”(NaN),正无穷大和负无穷大。
Number对象是Object类型的成员,它是内置对象Number的实例。
原始值Infinity表示一个正无穷大的数字,Number类型成员。
原始值NaN表示IEEE标准”Not-a-Number”值的集合,Number类型成员。
想象一下,假设你就是一个ECMAScript引擎。
当你接收到一条语句:
this.x = y;
你能确定该做什么吗?
很明显, 我们不知道该做些什么,因为我们既不知道this是什么,也不清楚y是什么。
所以,如果要正确执行这条语句,我们需要一个上下文,用以确定this和y到底是什么,这个上下文,就是执行环境。
通过在源文件中透过函数声明、函数表达式或内置Function对象来定义的函数对象。
内部函数对象,它们属于内置对象,如parseInt, Math.exp等等。
Global代码
Eval代码
Function代码
2. 调用Result(1)的[[HasProperty]]方法, 传递Identifier作为参数
3. 如果Result(2)是true, 则返回一个Reference(引用)类型的值,它的base object是Result(1),而它的property name是Identifier
4. 跳到第1步
5. 返回一个Reference类型,它的base object是null,它的property name是Identifier
标识符查找的结果通常是一个名字为标识符字符串的引用值。
内置对象,如 Math,String,Date,parseInt等等,它们都是不可枚举的(DontEnum)。
宿主属性,它自己可能会包含一个值为全局对象的属性,比如,在HTML 的DOM中,全局对象中的window属性,就是全局对象自己。
当控制器进入了执行环境,ECMAScript运行的时候,全局对象可能还会被添加上一些额外的属性,一些之前已有的属性也有可能被改变。
同一个执行环境中的this值是不变的。
arguments对象的内部属性[[prototype]],是原生对象prototype,初始值是Object.prototype
创建callee属性,不可枚举(DontEnum),其值为正在执行的函数对象,这使得匿名函数也可以进行递归。
创建length属性,不可枚举(DontEnum),其值为caller提供的实际参数数量。
按少于length的正整数数量创建ToString(arg)属性,不可枚举(DontEnum),第一个实际参数值对应为arg = 0,第二个对应为arg = 1,依此类推。当实际参数少于形参时,该属性会在活动对象中相应地共享它的值。意思就是说,改变此属性将改变活动对象中的属性值,反之亦然。
当控制器进入到一个执行环境中时,作用域链即被创建和初始化,变量实例化也开始进行,this值也被确定下来。
作用域链创建并初始,仅包含global对象。
变量实例化进行的时候以global对象作为变量对象,属性为不可删除(DontDelete) 。
This值为global对象。
当控制器进入到eval代码的执行环境中时,先前活动的执行环境,引用到调用环境*,用来决定作用域链,变量对象和this值。如果没有调用环境,则所有这些都以全局代码形式进行处理。
作用域链初始化时包含一个与调用环境相同的对象,并保持相同的顺序。这包含了通过with语句和catch子句添加到调用环境作用域链上的对象。
变量实例化时使用调用环境下的变量对象。
This值与调用环境下的this值一致。
* 调用函数语句执行时的execution context就是calling context
作用域链初始化时先添加活动对象,然后再添加该函数对象[[Scope]]属性中存储的其他对象。* 闭包机制
变量实例化执行时使用活动对象作为变量对象,属性为不可删除(DontDelete)。
This的值为Caller,如果caller不是对象(或者是null),则this值为global对象。
with语句会在当前执行环境中的作用域链顶端添加一个计算对象,在这个扩展的作用域链执行完语句之后,随机复原之前的作用域链。
With(表达式)语句的执行过程如下:
1.评估表达式
2.调用GetValue(Result(1))
3.调用ToObject(Result(2))
4.将Result(3)添加到 作用域链的顶端
5.用第4步扩展的作用域链来评估语句
6.使C=Result(5),如果在第5步时有异常抛出,则C=(throw,V,empty),V是这个异常(执行现在当作没有异常抛出继续进行)
7.在作用域链中移除Result(3)
8.返回C
注意:当控制器离开该“嵌入”的语句时,无论是正常还是异常,作用域链都将被恢复。
catch(标识符)块的执行过程如下:
1.使C为通过catch传递进来的参数
2.像new Object()一样创建一个新的对象
3.在Result(2) 的那个对象上创建一个property,名字是标识符,值是C,不可删除
4.将Result(2)添加到作用域链的顶端
5.评估这个块语句
6.将Result(2) 从作用域链中移除
7.返回Result(5)
function Identifier(FormalParameterList opt){FunctionBody}
函数声明的解析过程如下:
1.创建一个new Function对象, FormalParameterList指定参数,FunctionBody指定函数体。将当前正在运行的执行环境中的作用域链作为它的作用域。
2.为当前的变量对象 创建一个名为Identifier的属性,值为Result(1)。
function(FormalParameterList opt){FunctionBody}
匿名函数表达式的解析过程如下:
1.创建一个new Function对象, FormalParameterList指定参数,FunctionBody指定函数体。将当前正在运行的执行环境中的作用域链作为它的作用域。
2.返回Result(1)。
function Identifier(FormalParameterList opt){FunctionBody}
具名函数表达式的解析过程如下:
1.创建一个new Object对象
2.将Result(1)添加到作用域链的顶端
3.创建一个new Function对象,FormalParameterList指定参数,FunctionBody指定函数体。将当前正在运行的执行环境中的作用域链作为它的作用域。
4.为Result(1)创建一个名为Identifier的属性,其值为Result(3),只读,不可删除
5.从作用域链中移除Result(1)
6.返回Result(3)
函数对象构造过程如下:
1.如果已有对象E,它已有FunctionBody,且与现在给到的FunctionBody相等,则跳转到第13步
2. 创建一个新的ECMAScript native对象F
3.设置F的[[Class]]为“Function”
4.设置F的[[Prototype]]为原始的Function prototype对象
5.设 置F的[[Call]](参见之后的Slide)
6.设置F的[[Construct]](参见之后的Slide)
7.设置F的[[Scope]]为一个新的作用域链,它和当前作用域包含相同的对象
8.设置F的lengeh属性值为形参数量,如果未定义参数,则为0。9.以new Object()表达式方式创建一个新的对象
10.设置F的 constructor属性值为Result(9)
11.设置F的prototype属性值为Result(9)
12.返回F
13.酌情(由实现者决定)跳转到第2步或第14步
14.创建 一个新的ECMAScript native对象F,连接到 E,复制所有E和F的非内部属性*以使得它们与E和F的保持一致。
15.设置F的[[Class]]属性值为“ Function”
16.设置F的[[Prototype]]属性值为原始的Function prototype对象
17.设置F的[[Call]]属性
18.设置F的[[Construct]]属性
19. 设置F的[[Scope]]属性值为一个新的作用域链,它和当前作用域包含相同的对象
20.返回F
* 内部属性指的是所有以[[]]书写的属性
注意:
每个function都会自动创建一个prototype属性,以使得它们可以当作构造器来使用。
第1步,使得类似函数A中嵌套了一个不依赖于A的函数B的这种情况进行优化。在这种情形的实现中,允许在A每次被调用的时候,重用B这个对象。
第13步决定是否执行此 优化。如果在某个实现中选择不,则会跳转到第2步。
连接对象(很多引擎都未去做这个实现)
当两个或更多的Function对象连接时,它们具有如下特殊的行为:
1.任何时候,对 象O创建或设置一个非内部属性时,通信机制会立即在其他所有与O连接的对象上做相同的操作。
2.任何时候,对象O删除一个非内部属性, 通信机制会立即在其他所有与O连接的对象上做相同的操作。
3.如果对象O与P相连,它们可以通过==和===来进行比较。
4.当对象O与P相连 ,且对象P与Q相连,则O与Q也会自动相连。
注意:相连的对象除了它们各自不同的内部属性外,是很难进行区别的。而这些内部属性可能也只有[[Scope]]会不同。
[[Call]]
当函数对象F调用了[[Call]]属性,将执行以下步骤:
1.将F的形参表、传递的参数列表,和this植入到一个新的执行环境
2.评估F的FunctionBody
3.退出在第1步植入的执行环境,恢复之前的执行环境
4.如果Result(2).type是 throw,抛出Result (2).value
5.如果Result(2).type是return,返回Result(2).value
6.Result(2).type默认情况下,返回undefined
[[Construct]]
当函数对象F调用了[[Construct]]属性,将执行以下步骤:
1.创建一个新的ECMAScript native对象
2.将 Result(1)的[[Class]]属性值设为“Object”
3.取得F的prototype属性值
4.如果Result(3)是一个对象,将Result(1)的[[Prototype]]属性值设置为Result(3)
5.如果Result(3)不是一个对象,将Result(1)的[[Prototype]]属性值设置为原始的Object prototype对象
6.调用F的 [[Call]]属性,将Result(1)设置为this值,将[[Construct]]传递的参数当作参数列表
7.如果Type(Result(6))是一个对象,返回Result(6)
8.返回Result(1)
This对象的原型,该属性值只会是一个object或null,所有的[[Prototype]] chain最终都都会通向到null。
指明This对象类别的字符串值
与This对象关联的内部状态信息
返回指定属性的值
设置指定的属性值
返回是否可以执行[[Put]]指定属性的操作的Boolean值
返回对象是否存在指定的属性名的Boolean值
移除对象指定的属性
返回对象的默认值,只能是原始值,不允许对象和引用。
通过调用new操作符构造一个对象。
通过函数调用表达式执行与对象关联的代码。
返回一个Boolean值,表示This对象是否存在指定的委派(实例),仅对ECMAScript native中的Function对象实现。
作用域链,用于表示一个函数对象执行时的环境。
为正则表达式匹配和返回一个MatchResult的值。
http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,% 20December%201999.pdf
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
http://www.ecma-international.org/memento/index.html
下载本文的ECMAScript概述.ppt