前言
原型继承关系一直是一个比较复杂的点,最近看了《你不知道的JavaScript》才豁然开朗,再结合社区资料深入扩展才终于是啃下了这块知识。下面带大家来深入理解下原型继承之间的关系。
看图解析
下面这幅图大家肯定都不陌生,这是在社区广为流传的一副原型继承之间的关系图。画的也是特别好,但是如果你第一次直接去了解它,那你肯定是懵懵懂懂的,只有自己对原型有一定的认识才能真正的理解它所表达的含义。
整体上来都不知道该怎么下手,现在我们一步一步分解来看。
1.系统自带的构造函数 function Object
我们先从最熟悉的创建对象来看,首先你要明白创建对象无论是采用字面量的形式还是实例化Object构造函数来创建,本质上字面量的形式还是会从Object构造函数来进行创建。所以我们直接来了解实例化Object构造函数来创建对象的过程。
// 字面量
var obj1 = {}
// 实例化
var obj2 = new Object()
当我们执行 var obj2 = new Object() 时,会进行以下操作
// 将构造函数的prototype复制给创建对象的__proto__
obj2.__proto__ = Object.prototype
所以 上图中的 o1,o2对象的__proto__指向 Object.prototype 再看 Object构造函数 原型就是本身的原型 Object.prototype,这没什么好说的。 Object.prototype中的constructor指向本身构造函数 Object这也没什么好说的。 那既然Object.prototype是原型对象,那就也是个对象,是对象就会有__proto__,那它的__proto__指向的是谁呢?它指向的是null,为什么呢?因为它是最顶层的,所有对象的起源都源自于它,在它之上就没有原型了。
2.自己定义的构造函数 function Foo
和上面还是很相似的
var fn = new Foo()
// 当我们执行上面代码时,会进行以下操作
// 将构造函数的prototype复制给创建对象的__proto__
// fn.__proto__ = Foo.prototype
所以 上图中的 f1,f2对象的__proto__指向 Foo.prototype 同理 prototype 和 constructor 指向也毫无争议。 我们来看Foo.prototype的__proto__,它的指向是哪里呢? 首先我们要明白,函数既是函数也是对象。是对象的话就有__proto__ ("Foo的__proto__"这个我们最后研究),是函数的话就会有prototype 。Foo.prototype它是如何产生的呢?在这个函数被创建的时候函数里面就会创建一个叫 prototype的属性,它的值是一个对象,既然值是对象,那毫无疑问它内部创建肯定是通过实例化了Object构造函数创建所得。
// 类似于
Foo.prototype = new Object()
// Foo.prototype.__proto__ = Object.prototype
那就相当于我们上面的图一,所以它的指向毫无疑问是指向Object.prototype。
3.系统自带的构造函数 function Function()
同理 创建函数我们也可以通过构造函数来创建,和创建对象原理是一样的。
var fn = new Function()
对于 Function 的 prototype 和 constructor这两个和上面是一致的互相指向对方。 至于 Function.prototype指向Object.prototype 和上面 2中的Foo.prototype 指向原理是一致的,不懂的可以认真看看上面,这里就不重复解释了。
4.构造函数本身的__proto__ 指向
细心的你肯定还会发现我们还没有将Foo Object Fuction 三个构造函数的__proto__线讲解,下面让我们来看看它又是如何指向的呢?
- Foo的__proto__ --> Function.prototype
我们首先来看Foo函数,看以下代码
function Foo (){}
// 相当于
var Foo = new Function()
// 所以执行上面代码时会执行类似以下操作
// Foo.__proto__ = Function.prototype
我们看到了什么?相当于调用了构造函数来创建! 所以说 Foo的__proto__ 指向–> Function.prototype
- Object的__proto__ --> Function.prototype
同理如下
function Object (){}
// 相当于
var Object = new Function()
// 所以执行上面代码时会执行类似以下操作
// Object.__proto__ = Function.prototype
- Function.的__proto__ --> Function.prototype
这个看起来有点奇怪,这也是比较特殊的,相当于 Function.的__proto__ === Function.prototype 虽然它内部是做了一些操作,但是我们可以这样来理解它
function Function (){}
// 相当于
var Function= new Function()
// 所以执行上面代码时会执行类似以下操作
// Function.__proto__ = Function.prototype
这样就能理解了!
End
现在我们回过头去看这张图是不是非常清晰了?如果对你有帮助,点赞收藏加关注!如有错误,望各位大佬指正!
|