尝试一图理清prototype、proto、原型对象之间的关系

原型和原型链的关系错综复杂,最近借鉴了网上各位大神的文章,终于感觉搞懂了,于是马上写了这篇文章理清思路。

图示

js 复制代码
function Foo(){};
let foo = new Foo();

概念

在开始讲解之前我们要理清一些概念:

  1. 函数即是对象
  2. 原型对象(prototype object) :顾名思义就是 prototype 指向的对象,在 JavaScript 中,每当定义一个对象(函数) 时候,对象中都会包含一些预定义的属性,我们可以想象这些预定义的属性都在一个叫原型对象的地方存着,也就是说把对象当成两块去理解,一块是本体,一块是原型对象。原型对象本身又是一个普通对象,所以它也有自己的原型对象。
  3. __proto__constructor属性是对象独有的
  4. prototype 属性是函数独有的
  5. 构造函数:用来初始化新创建的对象的函数是构造函数。在例子中,Foo()函数是构造函数
  6. 实例对象:通过构造函数的new操作创建的对象是实例对象。可以用一个构造函数,构造多个实例对象

因此,对象拥有__proto__constructor属性。 函数拥有__proto__constructor以及prototype属性。 关于__proto__constructor以及prototype属性的作用,可以参考这篇文章里面关于它们的解释 尝试一篇文章说清JS继承(文字、内存、图片三方面解析__proto__、constructor、prototype) - 掘金 (juejin.cn)

于是我们就可以一点一点的补充出上面的图了。

从0绘出关系图

js 复制代码
function Foo(){};
let foo = new Foo();

最初版乞丐图

我们先从foo实例对象 ,以及Foo构造函数Foo的原型对象的关系下手:

验证一下:

js 复制代码
function Foo() {}
let foo = new Foo()
console.log(foo.constructor === Foo)
console.log(Foo.prototype === foo.__proto__)
console.log(Foo.prototype.constructor === Foo)

结果:

分析:

第三行中foo.constructor === Foo,foo上是没有constructor的,它的constructor是继承而来的,顺着__proto__找到Foo的原型对象,它有constructor属性,并且指向Foo构造函数,所以成立。

路径完善图

上图离我们最终形态差的还是有点远,前面说到对象应该有__proto__constructor,函数应该有__proto__constructorprototype属性,现在我们补齐:

验证一下:

js 复制代码
function Foo() {}
let foo = new Foo()
console.log(Foo.__proto__ === Function.prototype)
console.log(Foo.constructor === Function)
console.log(Foo.prototype.__proto__ === Object.prototype)

结果:

分析:

Foo的构造函数是Function函数,所以Foo的__proto__指向Function的原型对象,Foo的constructor指向Function函数,Foo的原型对象也是一个普通对象,它的构造函数是Object函数,所以Foo的原型对象的__proto__指向Object的原型对象。

现在可以看到foo,Foo,Foo原型对象都不差属性了,但又引入了Object和Function函数及其原型对象,接下来画的这部分就是JS规定好了的,无需纠结,记住就行。画的时候记住一点,所有的函数的构造函数源头都是Function函数,所有的对象的原型对象源头都是Object的原型就行。

最终实现图

把每个对象和函数需要的属性补齐。

验证一下:

js 复制代码
function Foo() {}
let foo = new Foo()
console.log(Function.constructor === Function)
console.log(Function.prototype === Function.__proto__)
console.log(Function.prototype.__proto__ === Object.prototype)
console.log(Object.prototype.__proto__ === null)
console.log(Object.constructor === Function)

结果:

分析:

Function函数的constructor指向它本身。

Function函数的prototype__proto__都指向Function 函数的原型对象。

Function函数的原型对象的__proto__指向Object的原型对象。

Object函数的原型对象的__proto__指向null

Object函数的constructor指向Function函数

上面的分析一部分是JS规定的,还有一部分就遵循画之前说的的原则了。

最后

总之,终于把它们之间的关系理清除了,如果有什么不对的地方欢迎指正。

参考资料

理解prototype、proto和constructor的关系

尝试一篇文章说清JS继承(文字、内存、图片三方面解析__proto__、constructor、prototype)

相关推荐
GISer_Jing15 分钟前
[总结篇]个人网站
前端·javascript
ss.li16 分钟前
TripGenie:畅游济南旅行规划助手:个人工作纪实(二十二)
javascript·人工智能·python
疯狂的沙粒36 分钟前
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
前端·uni-app·html
小妖66640 分钟前
html 滚动条滚动过快会留下边框线
前端·html
heroboyluck1 小时前
Svelte 核心语法详解:Vue/React 开发者如何快速上手?
前端·svelte
海的诗篇_1 小时前
前端开发面试题总结-JavaScript篇(二)
开发语言·前端·javascript·typescript
琹箐1 小时前
ant-design4.xx实现数字输入框; 某些输入法数字需要连续输入两次才显示
前端·javascript·anti-design-vue
程序员-小李1 小时前
VuePress完美整合Toast消息提示
前端·javascript·vue.js
Uyker2 小时前
从零开始制作小程序简单概述
前端·微信小程序·小程序
Dontla5 小时前
为什么React列表项需要key?(React key)(稳定的唯一标识key有助于React虚拟DOM优化重绘大型列表)
javascript·react.js·ecmascript