

上帝视角一文理解JavaScript原型和原型链
source link: https://segmentfault.com/a/1190000037427760
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文呆鹅原创,原文地址: https://juejin.im/user/307518987058686/posts
前言
本文将从 上帝角度
讲解JS的世界,在这个过程中,大家就能完全理解JS的原型和原型链是什么,之后还会基于原型和原型链知识拓展一些相关知识。
阅读本文前可以思考下面三个问题:
- 你理解中的原型和原型链是什么?
- 你能完全理解并画出原型和原型链的关系图吗?
- 基于原型和原型链拓展的相关知识你了解多少?
经典图
大家接触原型和原型链时应该都看到过下面这张图。刚开始了解的时候,看到这个图大都不太明白,甚至一脸懵,这里先留个坑。
先祭图,让暴风雨来得更猛烈些!
下面开始讲解JS世界是如何一步步诞生的,看完你也就完全明白这张神图啦。
无中生有
起初,上帝JS掌控的世界什么都没有。
上帝JS说:没有东西本身也是一种东西啊,于是就有了 null
:
现在我们要造点儿东西出来。但是没有原料怎么办?
有一个声音说:现在不是有 null
了嘛?
上帝说:那就无中生有吧!
JavaScript中的1号对象产生了,不妨把它叫做机器1号。
这个机器1号可不得了,它是JS世界的第一个对象,它是真正的万物始祖。它拥有的性质,是所有的对象都有的。
__proto__
是什么呢?是“生”的意思,或者换成专业点的叫法“继承”。
有中生有
刚开始造物,上帝当然想继续下去啦,既然已经有了一个始祖级的机器,剩下就好办了,因为一生二,二生三,三生万物嘛。
不过上帝很懒,他不想一个一个地亲手制造对象。于是他做了一台能够制造新对象的东西:
他给这个东西起了一个名字:Object。
但是这个Object制造对象时候,需要有一个模版,现在只有机器1号,它就取了机器1号当模版。图中的 prototype
就代表模板对象。
如何启动制造呢?通过 new
命令。你按下“new”按钮,新的对象就造出来了。
把这个过程写成代码就是:
var obj = new Object();
轰轰烈烈的造物运动开始了……
有生万物
有一天,上帝JS去看了上帝Java造的世界,发现上帝Java的世界好精彩,可不仅仅有Object对象,还有String对象、Number对象、Boolean对象等等。
于是上帝就思考了:那我可以多让机器造一些对象啊。
但是上帝觉得把这些工作都交给机器1号的话,机器1号太累了,不如让机器1号造一个机器2号来做这些工作。
重点说明下“这些工作”指的是:总体负责制造所有的对象,包含Object、String、Number、Boolean、Array,甚至还有之后的Function。当然它只是负责制造,并不一定会亲手去制造对象,可以通过制造对应的机器来帮助它制造对象
于是就有了机器2号:
(注: __proto__
写起来麻烦,我们之后用 [p]
来代替)
可能有的小伙伴注意到啦, Object
也指向了机器2号,这是因为机器2号是负责造对象的,当然也负责造 Object
对象啦。
接下来,既然机器2号是由机器1号造出来的,而 String、Number、Boolean、Array
这些对象是由机器2号造出来的,所以它们其实和 Object
一样,也自带了 new
命令:你按下“new”按钮,新的对象就造出来了。
但是Object有自己的模板:机器1号。而 String、Number、Boolean、Array
它们有模板吗?
其实机器2号在创建它们的时候并不是直接创建它们的,而是先创建了对应对象的机器作为模板,然后再由各自的机器来创建它们。
具体我画了String相关的图(其他Number、Boolean、Array等都是同一个道理的):
这样,这张图显示了JS世界中那些最基本的机器本身的原型链,以及它们的模板对象的原型链。
- 机器1号制造了机器2号,机器2号总体负责各种对象的制造
- 但是机器2号并不是直接造各种对象,而是通过先建造对应的机器,再由对应的机器来制造对象。如:对于String,
机器2号
先制造了机器String号
,然后由机器String号
来制造String,机器2号
只负责总体控制 - 虽然机器2号制造了各种各样的机器,但是因为机器2号是由机器1号制造的,所以这些被制造的机器所属权还是归于机器1号的,毕竟机器1号是始祖级的。
- 对象和对应的机器,通过
prototype
来连接。如:对于String,机器2号
和String
通过prototype
连接 - 每个机器都有且只有一个的对象,每个对象也都有且只有一个机器作为模板。
万物缺活力
上帝看着越来越丰富的世界非常高兴,但是总感觉缺点什么?
一个声音说:世界缺少活力呀
上帝说:那就造一个 能让世界动起来的对象
上帝给这个新对象的起了个名字叫:Funciton
但是这个制造Function的工作交给谁好呢,让世界动起来当然是非常重要的,那就交给机器2号吧, 由机器2号亲手负责Function的制造
于是,Function对象就出现了
让我们来观察一下Function对象:
prototype __proto__
于是我们得到了Function的一个非常特别的性质:
Function.__proto__ === Function.prototype
于是JavaScript的世界的变成了下面的样子:
到现在我们能明白啦:
- 机器1号 = Object.prototype
- 机器2号 = Function.prototype
- 机器String号 = String.prototype
世界动起来
自从有了Function,世界就越来越有活力了,有什么事需要做,用new Function()造个新Function来做就行了。
但是刚造出来的Function机器 很难用 ,用法就像下面这个:
let Foo = new Function("name", "console.log(name)"); Foo('dellyoung'); // 控制台打印出:dellyoung
你想要造一个Function,无论是输入的内容(参数)还是要做的事情(函数体)都得弄成字符串,才能成功造出来。
上帝用起来难受啊,他就改装了一下这个Function,给他来了个语法糖
function Foo(name) { console.log(name); } Foo('dellyoung'); // 控制台打印出:dellyoung
(注:上面两段代码是完全等价的。)
现在造一个新的Function就舒服多啦!
以造 Foo()
为例,于是JavaScript的世界的变成了下面的样子:
Function这个对象比较特殊,它new出来后,就是一个全新的对象了, function Foo()
(注意:它等价于 let Foo = new Function()
)和 Object
、 String
、 Number
等这些对象一样,都是对象。
既然都是对象,当然 function Foo()
也是由机器2号来控制制造的,但是机器2号很忙,它没有精力直接制造 function Foo()
,机器2号是通过制造出一个 制造function Foo()的机器
来制造 function Foo()
。
咱们称 制造function Foo()的机器
为 机器Foo()号
当然既然是机器,所以 机器Foo()号
也是 由机器1号
控制的,原因上文讲过:
虽然机器2号制造了各种各样的机器,但是因为机器2号是由机器1号制造的,所以这些被制造的机器所属权还是归于机器1号的,毕竟机器1号是始祖级的。
而且这个 function Foo()
对象制造出来后,它既然是对象,所以它和Object、String、Number等对象一样,可以通过 new Foo()
制造出新的对象,模板就是用的 机器Foo()号
。
听起来好像有点绕,咱们看看图就明白啦
上图中:
Object.prototype Function.prototype String.prototype Foo.prototype __proto__
回到现实
现在我们就能完全理解并完整的画出原型和原型链的关系图啦:
其实可以被用来 new
的对象或函数,我们都可以称之为构造函数,每个构造函数都和它的机器(也就是 XXX.prototype
)通过 constructor
相连,我们来画出构造函数和它们的 constructor
:
为了清晰一些,上图用 [con]
表示 constructor
现在这张图就是完整的原型和原型链的关系图啦
用正式的语言总结一下就是:
- 子类的__proto__属性,表示构造函数的继承,总是指向父类。
- 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
现在我们再看这张神图:
是不是很简单啦,不过就是把咱们画的图向右旋转了90°。
而且仔细看一遍,咱们的关系图包含的更加的全面。
填坑完毕。下篇文章我会以此为延伸,从底层讲解JavaScript的this,看完你会彻底理解this为何物,关注我
看完两件事
- 欢迎加我微信(iamyyymmm),拉你进技术群,长期交流学习
- 关注公众号「呆鹅实验室」,和呆鹅一起学前端,提高技术认知
:rainbow: 点个赞支持我吧 :rainbow:
Recommend
-
129
-
94
腾讯新闻春节H5因为春节的特殊场景,使得其被人感受的印象变得更深。而实际上,我们每天使用腾讯新闻,浏览上面各种高度契合自己的内容时,背后支撑的“千人千面”等技术,原理和春节H5一样。
-
73
奇思妙想 - @WhyAreYouSoSad - 今天突然想到这个问题,如果在现实中遇见另一个我(外形或性格都一直),我肯定不想和他成为朋友。这种是病吗?
-
24
上帝视角看 TypeScript 原创...
-
12
打破PPT26年的垄断,来画推出上帝视角演示工具Perfoo - IT业界_CIO时代网 - CIO时代—新技术、新商业、新管理打破PPT26年的垄断,来画推出上帝视角演示工具Perfoo 2021-07-29 16:12:02 来源: 摘要:打破PPT...
-
9
《青麓幽鸣· 青木》剧照传统式的戏剧表演,演员们在舞台上演绎悲欢离合,观众们看到的是角色...
-
7
10分钟学会从上帝视角看产品数据 ...
-
4
上帝视角来看 2022 年前端趋势 微博 使用《开发者头条》客户端,拥有更好的阅读体验。 立即体验
-
8
腾讯发布“智能高速”:开上帝视角 夜晚开车如白天般明亮 2022-07-28 15:44 出处/作者:快科技 整合编辑:佚名 0
-
6
如何高效地把握支付业务?或许我们可以从宏观角度入手,先对支付总架构有所认知。在这篇文章里,作者就从交易服务层、支付服务层、清算服务层等几大维度,对支付总架构进行了解析,一起来看看吧,或许对你建立支付业务的宏观视角会有所帮助。
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK