浅析 JavaScript 原型链与原型链式继承
文章目录
原型链与原型链式继承
上篇总结了下JavaScript的作用域链的问题,欢迎拍砖![浅析JavaScript作用域链]()
继上篇总结中提出的情况
同样都是链,但这两个链往上追朔的顶点是不一样的;并且为了增强我们对js继承的理解。
总结一下JavaScript原型链的问题。
prototype属性
首先我们要知道一个prototype属性,这个属性就是理解原型链的关键。提到这个属性,我们要区别一下,只有函数对象才有prototype属性,而普通对象是没有的。
函数对象:
|
|
普通对象:
|
|
原型对象
JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__
的内置属性,用于指向创建它的函数对象的原型对象prototype。
|
|
这个时候,我们就可以发现:
__proto__
指向创建它的函数对象的原型对象prototype
指向原型对象
这样就可以更好的理解原型对象的概念了!
constructor属性
原型对象prototype中都有个预定义的constructor属性,用来引用它的函数对象,简单来讲就是指向它的构造函数,当然这样讲是不严谨的,但是有助于我们理解它。
|
|
总结:
- 函数对象的prototype属性指向它的构造函数的原型对象prototype(只有函数对象拥有prototype属性)
- constructor属性指向它的构造函数
原型链
总结:
- 实例对象 f(通过
new XX()
所得到的实例),跟原型链相关的只有__proto__
属性,指向其对应的原型对象*.prototype
。 - 构造函数对象
foo
分原生和自定义两类。跟原型链相关的有__proto__
属性,除此之外还有prototype
属性。它们的__proto__
属性都是指向Function.prototype
这个原型对象的。prototype
也是指向对应的原型对象。 - 原型对象
foo.prototype
除了一样拥有__proto__
外,也拥有独有的属性 constructor 。它的__proto__
指向的都是Object.prototype
,除了Object.prototype
本身,它自己是指向null
。而constructor
属性指向它们对应的构造函数对象。 - 原型链是基于
__proto__
的。实例只能通过其对应原型对象的constructor
才能访问到对应的构造函数对象。构造函数只能通过其对应的prototype
来访问相应的原型对象。 - 当向上查找时,会查找到最顶层的构造函数的原型对象为止,而不像作用域链一样指向顶级作用域(也就是顶级对象
window
)为止。
原型链式继承
根据上边得出的结论,我们来稍微理解一下原型链式继承。
原型链式继承
|
|
可以看到,函数原型SubType用(修改自身prototype属性引用的原型对象)方式实现了继承,那么它的原型对象即是函数对象SuperType的实例,这样就可以理解:实例s(普通对象)可以调用它的父对象SuperType的getSuperValue方法。
这个继承方式也暴漏出了一些问题:如果原型中包含引用类型的值,则实例间对该值的修改会相互影响。因为js中只有两种类型的值,引用类型(通常指对象,包括数组和函数),基本类型(包括undefined、null、布尔值、数字和字符串)。
参考
- 《JavaScript权威指南》
- 《JavaScript高级程序设计》第三版
文章作者 ryan
上次更新 2016-01-10