本章是关于ECMAScript面向对象实现的第2篇,第1篇我们讨论的是概论和CEMAScript的比较,如果你还没有读第1篇,在进行本章之前,我强烈建议你先读一下第1篇,因为本篇实在太长了(35页)。
英文原文:
注:由于篇幅太长了,难免出现错误,时刻保持修正中。
在概论里,我们延伸到了ECMAScript,现在,当我们知道它OOP实现时,我们再来准确定义一下:
复制代码 代码如下:
ECMAScript is an object-oriented programming language supporting delegating inheritance based on prototypes.
ECMAScript是一种面向对象语言,支持基于原型的委托式继承。
我们将从最基本的数据类型来分析,首先要了解的是ECMAScript用原始值(primitive values)和对象(objects)来区分实体,因此有些文章里说的“在JavaScript里,一切都是对象”是错误的(不完全对),原始值就是我们这里要讨论的一些数据类型。
数据类型
虽然ECMAScript是可以动态转化类型的动态弱类型语言,它还是有数据类型的。也就是说,一个对象要属于一个实实在在的类型。
标准规范里定义了9种数据类型,但只有6种是在ECMAScript程序里可以直接访问的,它们是:Undefined、Null、Boolean、String、Number、Object。
另外3种类型只能在实现级别访问(ECMAScript对象是不能使用这些类型的)并用于规范来解释一些操作行为、保存中间值。这3种类型是:Reference、List和Completion。
因此,Reference是用来解释delete、typeof、this这样的操作符,并且包含一个基对象和一个属性名称;List描述的是参数列表的行为(在new表达式和函数调用的时候);Completion是用来解释行为break、continue、return和throw语句的。
原始值类型
回头来看6中用于ECMAScript程序的数据类型,前5种是原始值类型,包括Undefined、Null、Boolean、String、Number、Object。
原始值类型例子:
复制代码 代码如下:
var a = undefined;
var b = null;
var c = true;
var d = 'test';
var e = 10;
这些值是在底层上直接实现的,他们不是object,所以没有原型,没有构造函数。
大叔注:这些原生值和我们平时用的(Boolean、String、Number、Object)虽然名字上相似,但不是同一个东西。所以typeof(true)和typeof(Boolean)结果是不一样的,因为typeof(Boolean)的结果是function,所以函数Boolean、String、Number是有原型的(下面的读写属性章节也会提到)。
想知道数据是哪种类型用typeof是最好不过了,有个例子需要注意一下,如果用typeof来判断null的类型,结果是object,为什么呢?因为null的类型是定义为Null的。
复制代码 代码如下:
alert(typeof null); // "object"
显示"object"原因是因为规范就是这么规定的:对于Null值的typeof字符串值返回"object“。
规范没有想象解释这个,但是Brendan Eich (JavaScript发明人)注意到null相对于undefined大多数都是用于对象出现的地方,例如设置一个对象为空引用。但是有些文档里有些气人将之归结为bug,而且将该bug放在Brendan Eich也参与讨论的bug列表里,结果就是任其自然,还是把typeof null的结果设置为object(尽管262-3的标准是定义null的类型是Null,262-5已经将标准修改为null的类型是object了)。
Object类型
接着,Object类型(不要和Object构造函数混淆了,现在只讨论抽象类型)是描述 ECMAScript对象的唯一一个数据类型。
Object is an unordered collection of key-value pairs.
对象是一个包含key-value对的无序集合
对象的key值被称为属性,属性是原始值和其他对象的容器。如果属性的值是函数我们称它为方法 。
例如:
复制代码 代码如下:
var x = { // 对象"x"有3个属性: a, b, c
a: 10, // 原始值
b: {z: 100}, // 对象"b"有一个属性z
c: function () { // 函数(方法)
alert('method x.c');
}
};
alert(x.a); // 10
alert(x.b); // [object Object]
alert(x.b.z); // 100
x.c(); // 'method x.c'
动态性
正如我们在第17章中指出的,ES中的对象是完全动态的。这意味着,在程序执行的时候我们可以任意地添加,修改或删除对象的属性。
例如:
复制代码 代码如下: