javascript|[[Prototype]] ——原型链两万字全面解析「建议收藏」( 五 )


那么有没有更直接的方法来做到这一点呢?当然!功臣就是 Object.create , 不过我们现在暂时不介绍它 。


那人家都说不介绍了 , 咱就继续往下看呗 。
关于名称在 JavaScript 中 , 我们并不会将一个对象复制到另一个对象 , 只是将它们关联起来 。 从视觉角度来说 ,[[Prototype

机制如下图所示 , 箭头从右到左 , 从下往上:

image-20220413151203405
这个机制通常被称为「原型继承」 , 它常常被视为动态语言版本的类继承 。 这个名称主要是为了对应面向类的世界中「继承」的意义 , 但是违背了动态脚本对应的语义 。

照字面意思 , 似乎继承这个词语 , 在 JavaScript 中并不准确 。
「继承」这个次会让人产生非常强的心理预期 。 仅仅在前面加上「原型」并不能区分出 JavaScript 中和类继承*几乎完全相反的行为* , 因此在 20 年中造成了极大的误解 。

什么叫完全相反的行为?看来不是并不准确 , 而是根本没有继承 。
在我看来 , 在「继承」前面加上「原型」对于事实的曲解就好像是一只手拿橘子一只手拿苹果 , 然后把苹果叫做「红橘子」一样 。 无论添加什么标签都无法改变事实:一种水果是苹果 , 而另一种是橘子 。

根据上面的资料 , JavaScript 中仅仅是将原型绑定在同一对象 , 并没有继承 。
更好的方法是直接把苹果叫做苹果——使用更准确并且直接的术语 。 这样有助于理解它们的相似之处以及不同之处 , 因为我们大家都明白「苹果」的含义 。

什么啊?继承和原型完全不是一码事的比喻吗?
因此我认为这个容易混淆的组合术语「原型继承」严重影响了大家对于 JavaScript 机制真实原理的理解 。

原型继承这个词语是说前面的红橘子一样 , 不伦不类 。
继承意味着复制操作 , JavaScript 默认并不会复制对象属性 。 相反 , JavaScript 会在两个对象之间创建一个关联 , 这样一个对象就可以通过委托访问另一个对象的属性和函数 。 委托这个术语可以更加准确地描述 JavaScript 中对象的关联机制 。

这是重点 , JavaScript 不存在对象的复制 , 所以继承无从谈起 。
JavaScript 是通过委托的方式将两个对象关联在一起 。 这是 JavaScript 中原型的机制 。
还有个偶尔会用到的 JavaScript 术语差异继承 。 基本原则是在描述对象行为时 , 使用其不同于普遍描述的特质 。 举例来说 , 描述汽车时你会说汽车是四个轮子的一种交通工具 , 但是你不会重复描述交通工具具备的通用特性 。
如果你把 JavaScript 中对象的所有委托行为都归结到对象本身 , 并且把对象看作是实物的话 , 那就可以理解差异继承了 。
但是和原型继承一样 , 差异继承更多的是你脑中构建出的模型 , 而非真实情况 。 它忽略了一个事实 , 那就是对象 B 实际上并不是被差异构造出来的 。 我们只是定义了 B 的一些指定特性 , 其他没有定义的东西都变成了「洞」 。 而这些洞最终会被委托填满 。
默认情况下 , 对象并不会像差异继承暗示的那样通过复制生成 。 因此 , 差异继承也不适合用来描述 JavaScript 的 [[Prototype

机制 。
当然 , 如果你喜欢 , 完全可以使用继承这个术语 , 但是无论如何它只适用于你脑中的模型 , 并不符合引擎的真实行为 。

脑中的行为 , 而非真实的行为 。