用魔幻舞台剧讲解 JS 原型链的前世今生

62 阅读4分钟

用魔幻舞台剧讲解 JS 原型链的前世今生

今天用一则魔幻舞台剧来讲解 JS 原型链的前世今生。

导演设定

导演: JS 引擎(C++ 语言)

导演设定的开场人物:

  • 普通人:Object
  • 魔法师:Function

导演设定的开场布景:

  • 万物博物馆:Object.prototype
  • 魔法学院:Function.prototype

开场人物和物品关系

魔法师 Function 用 Function = new Function() 生成了自己
<--对应的代码关系--> Function.constructor === Function

魔法师 Function 用 Object = new Function() 魔法幻化出了普通人 Object
<--对应的代码关系--> Object.constructor === Function

普通人 Object 住在万物博物馆中,因此万物博物馆门上挂上了他家的标识
<--对应的代码关系--> Object.prototype.constructor === Object

魔法学院是万物博物馆中的一件藏品,建在博物馆里的一个指定的地方
<--对应的代码关系--> Function.prototype.__proto__ === Object.prototype

魔法师 Function 住在魔法学院 Function.prototype 中,因此魔法学院门口挂上了他的标识
<--对应的代码关系--> Function.prototype.constructor === Function

魔法学院 Function.prototype 记录和展示了魔法师 Function 所会的各种魔法,同时魔法师 Function 也在此修炼自己的魔法
<--对应的代码关系--> Function.__proto__ === Function.prototype

普通人 Object 是魔法师 Function 幻化的,因此他被允许到魔法学院学习里面的魔法
<--对应的代码关系--> Object.__proto__ === Function.prototype

舞台剧开演

开场人物与物品关系设定好了以后,JS 魔幻舞台剧就开演了。

魔法师 Function 按照导演要求的剧情用 Elf = new Function() 魔法又幻化出了精灵对象(Elf),同时导演(JS 引擎)在万物博物馆中指定了一个新的房间叫做精灵对象魔法专区(Elf.prototype)
<--对应的代码关系--> Elf.constructor === Function

精灵对象魔法专区这个房间中展示了各式各样的精灵,他们可以在此学习和使用的魔法

由于这个精灵魔法专区的房间也是建在万物博物馆中,所以
<--对应的代码关系--> Elf.prototype.__proto__ === Object.prototype

精灵对象住在这个叫做精灵对象魔法专区的房间中,因此在房间的门上挂上了精灵对象的标识
<--对应的代码关系--> Elf.prototype.constructor === Elf

精灵对象是魔法师 Function 幻化的,因此精灵对象被允许到魔法学院学习里面的魔法
<--对应的代码关系--> Elf.__proto__ === Function.prototype

剧情继续推演

精灵对象 Elf 用 blueElf = new Elf() 魔法幻化出了一个蓝精灵实体
<--对应的代码关系--> blueElf.constructor === Elf

蓝精灵是精灵对象中的一种,因此他可以去精灵对象魔法专区去学习和使用精灵魔法
<--对应的代码关系--> blueElf.__proto__ === Elf.prototype

蓝精灵 blueElf 想知道如果精灵对象魔法专区中没有的魔法他是否可以去魔法学院 Function.prototype 学习和使用?
<--对应的代码关系--> blueElf.__proto__.__proto__ === Function.prototype??

答案是否定的 blueElf.__proto__.__proto__ !== Function.prototype

原因是蓝精灵 blueElf 不是魔法师 Function 直接幻化的,蓝精灵不被允许进入魔法学院 Function.prototype 学习和使用里面的魔法。

对于精灵对象魔法专区中没有的本事,蓝精灵可以去万物博物馆里碰碰运气,看看能不能学到和使用其他的技能
<--对应的代码关系--> blueElf.__proto__.__proto__ === Object.prototype

到此,剧情和人物关系已经一目了然了。但是故事是不会停下脚步的......

故事的转折

某天,忽然一阵妖风吹过,把 Function.prototype 魔法学院门口挂着的 Function 魔法师的标识吹走了,原来挂标识的地方空空如也......
<--对应的代码关系--> Function.prototype.constructor = function(){}

普通人 Object 对象和精灵对象 Elf 仍旧可以来魔法学院 Function.prototype 里面学习魔法,但是却再也学不到标识魔法了
<--对应的代码关系--> Object.__proto__.constructor === function(){}Elf.__proto__.constructor === function(){}

恶作剧的后果

又过了一阵子,普通人 Object 对象觉得日子太平淡了,就使用了魔法 Elf.prototype = Object.create(Function.prototype) 来搞了一个恶作剧。这个恶作剧的后果是把精灵对象魔法专区的精灵标识变消失了,同时把精灵对象魔法专区的房间移到了魔法学院 Function.prototype 里面。

<--对应的代码执行后的结果--->

Elf.prototype {
  constructor: undefined,
  __proto__: Function.prototype
}

蓝精灵一觉醒来,发现自己除了可以学习精灵对象魔法专区里面的魔法,现在连魔法学院 Function.prototype 里面的魔法都可以学了。当然,他还是可以去更大的舞台万物博物馆中学习里面有的一切技术和魔法。

在开启学习和冒险之旅前,蓝精灵觉得还是要把自家精灵对象魔法专区的标识修好,于是他在门上重新挂上了精灵对象魔法专区的标识
<--对应的代码关系--> Elf.prototype.constructor = Elf

JS 世界中的冒险故事就此开始了......