JavaScript中的继承机制和传统的面向对象语言如C++和Java等基于类的继承机制不同,JavaScript采用基于原型的继承机制。JavaScript中没有类这样的定义,所有都是对象,包括函数。每个对象都有一个与之关联的原型对象,每一个对象都从原型继承属性。
JavaScript中有两个特殊的对象Object和Function,它们都是构造函数,用于生成对象,同时其本身也是对象,对应两个原型对象Object.prototye和Function.Prototype。
其中Object.prototye是所有对象的祖先,Function.Prototype是所有函数的原型。
我们把对象分为三类:
用户创建的对象:通过new调用生成的普通对象,如var foo=new Foo();
构造函数对象:指普通的构造函数,如Foo、Object和Function
原型对象:构造函数prototype属性所指向的对象,如Foo.prototype、Object.prototype和Function.Prototype
这三类对象都有一个_proto_属性(用户不可见),用于指向该对象的原型。
所有的对象都有一个constructor属性,指向对应的构造函数。构造函数对象还有一个prototype属性指向其构造对象的原型。
Object.prototype具有的基本属性
toString
|
function
|
|
toLocalString
|
function
|
|
valueOf
|
function
|
|
constructor
|
function
| 对象的构造函数 |
propertyIsEnumerable
|
function
|
自有属性是否可枚举
|
hasOwnProperty |
function
|
是否有自有属性
|
isPropertyOf
|
function
|
call
|
function
|
|
apply
|
function
|
|
Caller
|
function
|
|
bind
|
function
|
|
arguments
|
object
|
传入实际参数对象
|
length
|
number
|
函数形参个数
|
prototype
|
object
|
原型对象
|
function Foo(){} //创建两个对象 Foo和Foo.prototype
var foo=new Foo(); //创建foo对象
对象和原型直接关系如下图所示,其中
蓝色代表_proto_属性指向,
红色为prototype属性指向。
对象直接指向关系有点复杂,当你看懂这张图的关系,就看懂了原型之间的关系。总结有以下几点:
(1) 所有构造函数对象的_proto_都指向Function.prototype,包括Function对象。Foo._proto_ === Object._proto_ === Function._proto_ === Function.prototype。(Function.Prototype是所有函数的原型)
(2)所有函数对象的constructor都指向Function,包括Function。Foo.constructor === Function.constructor === Object.constructor === Function
(3)所有对象的_proto_属性指向的都是原型对象,_proto_属性本身表示就是该对象对应的原型。
(4)所有原型对象的_proto_属性都指向Object.prototype(这里没有考虑继承,即使有继承关系也可以按照原型链追溯到Object.prototype),而Object.prototype的_proto属性指向null。(Object.prototye是所有对象的祖先)
(5)函数对象的_proto_属性和prototype属性含义不一样,其中_proto_属性表示其本身的原型,prototype属性是其构造出来的对象的原型。
(6)为了获取普通对象的原型,一般先获得其constructor,如foo.constructor.prototype === Foo.prototype === foo._proto_
注意:上述_proto_属性对用户并不可见,不能通过foo._proto_方式访问,这里只是为了阐述方便。