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

[转]JavaScript对象模型-执行模型

数据类型
基 本数据类型
基本数据类型是JS语言最底层的实现。
简单数值类型: 有Undefined, Null, Boolean, Number和String。注意,描述中的英文单词在这里仅指数据类型的名称,并不特指JS的全局对象N an, Boolean, Number, String等,它们在概念上的区别是比较大的。
对象: 一个无序属性的集合,这些属性的值为简单数值类型、对象或者函数。同上,这里的对象并不特指全局对象Object。
函数: 函数是对象的一种,实现上内部属性[[Class]]值为"Function",表明它是函数类型,除了对象的内部属性方法外,还有 [[Construct]]、[[Call]]、[[Scope]]等内部属性。函数作为函数调用与构造器(使用new关键字创建实例对象)的处理机制不 一样(Function对象除外),内部方法[[Construct]]用于实现作为构造器的逻辑,方法[[Call]]实现作为函数调用的逻辑。同上, 这里的函数并不特指全局对象Function。
函数在JS这个Prototype语言中可以看作是面向对象语言的类,可以用它来构造对象实例。既 然函数可以看作是类,所以每一个函数可以看作是一种扩展数据类型。

内置数据类型(内置对象)
Function: 函数类型的用户接口。
Object: 对象类型的用户接口。
Boolean, Number, String: 分别为这三种简单数值类型的对象包装器,对象包装在概念上有点类似C#中的Box/Unbox。
Date, Array, RegExp: 可以把它们看作是几种内置的扩展数据类型。

首先,Function, Object, Boolean, Number, String, Date, Array, RegExp等都是JavaScript语言的内置对象,它们都可以看作是函数的派生类型,例如Number instanceof Function为true,Number instanceof Object为true。在这个意义上,可以将它们跟用户定义的函数等同看待。
其次,它们各自可以代表一种数据类型,由JS引擎用native code或内置的JS代码实现,是暴露给开发者对这些内置数据类型进行操作的接口。在这个意义上,它们都是一种抽象的概念,后面隐藏了具体的实现机制。
在 每一个提到Number, Function等单词的地方,应该迅速的在思维中将它们实例化为上面的两种情况之一。

数据 类型实现模型描述
数据实现模型描述
Build-in *** data structure: 指JS内部用于实现***类型的数据结构,这些结构我们基本上无法直接操作。
Build-in *** object: 指JS内置的Number, String, Boolean等这些对象,这是JS将内部实现的数据类型暴露给开发者使用的接口。
Build-in *** constructor: 指JS内置的一些构造器,用来构造相应类型的对象实例。它们被包装成函数对象暴露出来,例如我们可以使用下面的方法访问到这些函数对象:

//Passed in FF2.0,?IE7,?Opera9.25,?Safari3.0.4 
// access?the?build-in?number?constructor 
var ?number? = ? new ?Number( 123 );
var ?numConstructor1? = ?number.constructor;? // or 
var ?numConstructor2? = ? new ?Object( 123 ).constructor;
// both numConstructor1 and numConstructor2 are the build-in Number constructor 
numConstructor1? == ?numConstructor2? // result:?true 
// access?the?build-in?object?constructor 
var ?objConstructor1? = ?{}.constructor;? // or 
var ?objConstructor2? = ? new ?Object().constructor;
// both objConstructor1 and objConstructor2 are the build-in Object constructor 
objConstructor1 == objConstructor2? // result:?true



具体实现上,上图中横向 之间可能也存在关联,例如对于build-in data structure和constructor,Function、 Date、 Array、 RegExp等都可以继承Object的结构而实现,但这是具体实现相关的事情了。

关于简单数值类型的对象化
这 是一个细微的地方,下面描述对于Boolean, String和Number这三种简单数值类型都适用,以Number为例说明。
JS规范要 求: 使用var num1=123;这样的代码,直接返回基本数据类型,就是说返回的对象不是派生自Number和Object类型,用num1 instanceof Object测试为false;使用new关键字创建则返回Number类型,例如var num2=new Number(123); num2 instanceof Number为true。
将Number当作函数调用,返回结果会转换成简单数值类 型。下面是测试代码:

// Passed in FF2.0,?IE7,?Opera9.25,?Safari3.0.4 
var ?num1? = ? new ?Number( 123 );? // num1?derived?from?Number?&?Object 
num1? instanceof ?Number? // result:?true 
num1? instanceof ?Object? // result:?true
// convert?the?num1?from?Number type to?primitive?type, so it's no longer an instance of Number or Object 
num1? = ?Number(num1); 
num1? instanceof ?Number? // result:?false 
num1? instanceof ?Object? // result:?false 
var ?num2? = ? 123 ;? // num2?is?a?primitive?type 
num2? instanceof ?Number? // result:?false 
num2? instanceof ?Object? // result:?false


虽 然我们得到了一个简单数值类型,但它看起来仍然是一个JS Object对象,具有Object以及相应类型的所有属性和方法,使用上基本没有差别,唯一不同之处是instanceof的测试结果。

Prototype继承
Prototype
每 个对象都有一个[[Prototype]]的内部属性,它的值为null或者另外一个对象。函数对象都有一个显示的prototype属性,它并不是内部 [[Prototype]]属性。不同的JS引擎实现者可以将内部[[Prototype]]属性命名为任何名字,并且设置它的可见性,只在JS引擎内部 使用。虽然无法在JS代码中访问到内部[[Prototype]](FireFox中可以,名字为__proto__因为Mozilla将它公开了),但 可以使用对象的isPrototypeOf()方法进行测试,注意这个方法会在整个Prototype链上进行判断。
使用 obj.propName访问一个对象的属性时,按照下面的步骤进行处理(假设obj的内部[[Prototype]]属性名为__proto__):
1. 如果obj存在propName属性,返回属性的值,否则
2. 如果obj.__proto__为null,返回undefined,否则
3. 返回obj.__proto__.propName
调用对象的方法跟访问属性搜索过程一样,因为方法的函数对象就是对象的一个属性值。
提 示: 上面步骤中隐含了一个递归过程,步骤3中obj.__proto__是另外一个对象,同样将采用1, 2, 3这样的步骤来搜索propName属性。

例如下图所示,object1将具备