所以你在想 JavaScript 中 prototype
和 __proto__
的含义?它们不是完全相同的吗?让我们一起寻找答案。
对 prototype 的解释
苹果最近发布了它的新 iPhone,iPhone 11。这部手机有确定的特性 —— 例如,Face ID 和 4K 视频。生产的每部 iPhone 11 必须具有以上相同特性。
现在,让我们假定存在一个构造函数,每当被调用,它就生产一部新 iPhone 11。为了正确建造 iPhone 11,需要一台原型 —— 用来参考的 iPhone 11 模型。这份原型或模型确保每部 iPhone 11 都有 Face ID,能拍摄 4K 视频。因此,iPhone 构造函数必须知道并且能获得它要建造机器的原型。这就是构造器的 prototype
属性。
function iPhone() {}; // constructor
// a method for recognizing faces
iPhone.prototype.faceID = function() {};
// a method for taking 4k video
iPhone.prototype.video = function() {};
let newPhone = new iPhone(); // an iPhone 11
迄今为止都没有问题,对吧?接下来让我们进入 __proto__
。
prototype 与 \_\_proto__ 的关系
我已经生产了一台 iPhone 11,把它存到了名为 newPhone 的变量中。newPhone 的内容看上去就像这样:
所以似乎新 iPhone 11 包含 Face ID 和 video!事实上,你可以执行 newPhone.faceID()
或 newPhono.video()
,它们都能正常工作。但是,为何这些特性被存储在名为 __proto__
的对象上,而非直接作为 newPhone 的属性?
__proto__
是每个类实例上的对象,指向创建它的 prototype
。这儿,newPhone.__proto__
是 iPhone.prototype
的引用,因此和后者持有相同的内容。通过包含一个和 iPhone.prototype
相同的 __proto__
属性,newPhone 基本上在说,“看,既然我是一台 iPhone 11,我就具有其它任何 iPhone 11 一样的功能!我有 Face ID,4K 视频,和任何你能说出的功能。”
实际上,prototype
和 __proto__
唯一真实区别在于,前者是类构造器的属性,而后者是类实例的属性。换句话说,由于 iPhone.prototype
提供了一份构建 iPhone 的蓝图,newPhone.__proto__
确认自己是根据那份特定蓝图构建的。至于这两个对象上的属性和方法,好吧,它们完全相同。
最后,你可能在想最后一行 __proto__: Object
的含义。这是因为 newPhone.__proto__
实际上是一个 JavaScript 对象,JavaScript 对象也由特定 “蓝图” 构建而来。本例中,newPhone.__proto__.__proto__
指向 Object.prototype
,它是所有 JavaScript 对象的原型或蓝图。仅此而已!
延伸阅读
本文译自 medium,译者 LOGI
如有问题请在下方留言,文章转载请注明出处,详细交流请加下方群组!请大佬不要屏蔽文中广告,因为它将帮我分担服务器开支,如果能帮忙点击我将万分感谢。