本文深入解析JavaScript中prototype与__proto__的核心用法。通过代码实例对比普通对象与函数对象在原型属性上的差异,阐明__proto__作为内部指针指向构造函数prototype的机制,并结合图示梳理从实例到Object.prototype的完整继承路径,帮助开发者清晰理解JS面向对象编程中的原型链原理。
JavaScript原型链深度解析:prototype与__proto__的区别与联系
本文通过具体实例详细解析JavaScript中prototype与__proto__的应用方式,旨在为读者提供清晰的参考指南。
基础代码示例与输出分析
首先通过一个基础代码示例来引入概念。
function Foo() {
}
var foo = new Foo();
console.log(foo.prototype);// undefined
console.log(foo.__proto__ === Foo.prototype);// true
console.log(Foo.__proto__); [Function]
观察Foo.__proto__的输出结果如下:

console.log(Foo.prototype);// [object Object]
查看Foo.prototype的输出结果如下:

console.log(Foo.prototype.prototype);// undefined
原型属性机制详解
上述代码示例揭示了以下关键机制:
1、foo是Foo构造函数的一个实例,它属于普通对象而非函数,因此不具备prototype属性;
Foo本身是Function构造函数的实例,而Function是一个函数,其生成的实例Foo同样也是函数,因此它们都拥有prototype属性。此外,Object、Array、RegExp等内置构造函数也是函数,但Math仅是一个通过new Object()创建的普通对象,并非函数。
2、构造函数的prototype属性,在默认情况下等同于一个通过new Object()创建的对象,并额外包含一个constructor属性。这意味着,非函数对象默认没有prototype属性,只有__proto__属性。
除了Object.prototype这一特殊对象外,JavaScript中所有其他对象均具备__proto__属性;而只有函数对象才拥有prototype属性。
在创建对象时,系统会自动生成一个__proto__属性,该属性指向其对应构造函数的prototype。当访问对象自身的属性时,若未找到,引擎会沿着__proto__指向查找构造函数prototype中对应的属性,从而实现了属性的继承。
只有在定义函数时才会创建prototype属性,其核心目的正是为了实现上述的继承机制。
核心概念总结
核心总结:
<1>无论是普通对象还是函数对象,它们内部都隐含一个名为“__proto__”的属性,这通常被称为原型属性,其本质是一个Object类型的对象。
<2>对于函数对象,它们额外拥有一个prototype属性。该属性与由它作为构造函数创建的普通对象的__proto__属性是等价的,即满足“new XXXt().__proto__ === XXX.prototype”为真。这意味着对象XXX中存在的__proto__属性是一个指针,它指向XXX构造函数中的prototype属性。
原型链关系图解说明
以下摘录自网络资料以辅助理解:
一张示意图(橙色箭头表示初始关系,绿色箭头表示执行 var Fish = new Fu... 创建的过程,蓝色箭头表示执行f1= new Fish()创建的过程)。

通过这种机制,f1可以通过__proto__访问Fish.prototype中的属性(这是程序执行时自动查找的结果)。Fish可以访问Function.prototype定义的属性,而所有对象最终都可以访问Object.prototype中的属性。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码的运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述内容能对大家的JavaScript程序设计有所帮助。