一图带你深入理解原型继承关系

前言

原型继承关系一直是一个比较复杂的点,最近看了《你不知道的JavaScript》才豁然开朗,再结合社区资料深入扩展才终于是啃下了这块知识。下面带大家来深入理解下原型继承之间的关系。

看图解析

下面这幅图大家肯定都不陌生,这是在社区广为流传的一副原型继承之间的关系图。画的也是特别好,但是如果你第一次直接去了解它,那你肯定是懵懵懂懂的,只有自己对原型有一定的认识才能真正的理解它所表达的含义。

C93JJXJ3Q83ZFAPD@1DC@_W.png

整体上来都不知道该怎么下手,现在我们一步一步分解来看。

1.系统自带的构造函数 function Object

我们先从最熟悉的创建对象来看,首先你要明白创建对象无论是采用字面量的形式还是实例化Object构造函数来创建,本质上字面量的形式还是会从Object构造函数来进行创建。所以我们直接来了解实例化Object构造函数来创建对象的过程。

// 字面量
var obj1 = {}
// 实例化
var obj2 = new Object()

image.png

当我们执行 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

image.png

和上面还是很相似的

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构造函数创建所得。

扫描二维码关注公众号,回复: 14728346 查看本文章
// 类似于
Foo.prototype = new Object()
// Foo.prototype.__proto__ = Object.prototype

那就相当于我们上面的图一,所以它的指向毫无疑问是指向Object.prototype。

3.系统自带的构造函数 function Function()

image.png

同理 创建函数我们也可以通过构造函数来创建,和创建对象原理是一样的。

var fn = new Function()

对于 Function 的 prototype 和 constructor这两个和上面是一致的互相指向对方。
至于 Function.prototype指向Object.prototype 和上面 2中的Foo.prototype 指向原理是一致的,不懂的可以认真看看上面,这里就不重复解释了。

4.构造函数本身的__proto__ 指向

细心的你肯定还会发现我们还没有将Foo Object Fuction 三个构造函数的__proto__线讲解,下面让我们来看看它又是如何指向的呢?

image.png

  1. Foo的__proto__ --> Function.prototype
    我们首先来看Foo函数,看以下代码
function Foo (){}
// 相当于
var Foo = new Function()
// 所以执行上面代码时会执行类似以下操作
// Foo.__proto__ = Function.prototype

我们看到了什么?相当于调用了构造函数来创建!
所以说 Foo的__proto__ 指向–> Function.prototype

  1. Object的__proto__ --> Function.prototype
    同理如下
function Object (){}
// 相当于
var Object = new Function()
// 所以执行上面代码时会执行类似以下操作
// Object.__proto__ = Function.prototype
  1. Function.的__proto__ --> Function.prototype
    这个看起来有点奇怪,这也是比较特殊的,相当于 Function.的__proto__ === Function.prototype
    虽然它内部是做了一些操作,但是我们可以这样来理解它
function Function (){}
// 相当于
var Function= new Function()
// 所以执行上面代码时会执行类似以下操作
// Function.__proto__ = Function.prototype

这样就能理解了!

End

现在我们回过头去看这张图是不是非常清晰了?如果对你有帮助,点赞收藏加关注!如有错误,望各位大佬指正!

QQ图片20200210181218.jpg

猜你喜欢

转载自blog.csdn.net/kzj0916/article/details/123291576