3.5.2 原型对象
每个对象都有一个原型。对象的原型既可以是一个对象,即原型对象,也可以是null值。原型对象又有其自身的原型,因此对象的原型会形成一条原型链,原型链将终止于null值。原型对象本质上是一个普通对象,用于在不同对象之间共享属性和方法。对象与其原型之间具有隐含的引用关系,如图3-7所示。
在图3-7中,animal、dog和cat均表示对象。dog和cat对象的原型对象均为animal对象;而animal对象的原型为null值。dog和cat与其原型animal之间具有隐含的引用关系,该关系是通过对象的一个内部属性来维持的,即图3-7中的“[[Prototype]]”属性。所谓隐含的引用关系是指,对象的原型不是对象的公共属性,因此无法通过对象属性访问来直接获取对象的原型。该图也展示了对象的原型会形成一条原型链,例如从dog到animal并终止于null值的虚线就表示了一条原型链。
原型能够用来在不同对象之间共享属性和方法,JavaScript中的继承机制也是通过原型来实现的。原型的作用主要体现在查询对象某个属性或方法时会沿着原型链依次向后搜索,如图3-8所示。
在访问dog对象上的color属性时,先尝试在dog对象上查找该属性。若找到color属性,则返回属性值;若没有找到color属性,则沿着原型链在原型对象animal中继续查找color属性。此例中,dog对象没有color属性而animal对象包含了color属性,因此最终会返回animal对象上的color属性值。如果直到原型链的尽头(null值)也没有找到相应属性,那么会返回undefined值而不是产生错误。
如果对象本身和其原型对象上同时存在要访问的属性,那么就会产生遮蔽效果。在这种情况下,当前对象自身定义的属性拥有最高的优先级,如图3-9所示。
此例中,在dog对象和animal对象上都定义了color属性。在dog对象上读取color属性时,dog对象自身定义的color会被优先选用,而原型对象animal上的color属性会被忽略。
需要注意的是,原型对象在属性查询和属性设置时起到的作用是不对等的。在查询对象属性时会考虑对象的原型,但是在设置对象属性时不会考虑对象的原型,而是直接修改对象本身的属性值。