JavaScript原型继承本质是动态委托,核心为[[Prototype]]链接、函数prototype属性及属性查找时的逐级委托;prototype是函数属性,__proto__是对象内部链接,二者通过p.__proto__ === Person.prototype建立继承关系。

JavaScript对象原型继承的底层实现,核心在于理解三个相互咬合的机制:对象内部的[[Prototype]]链接、函数的prototype属性、以及引擎在属性访问时的逐级委托查找行为。它不是“复制”,而是“动态委托”——对象自身不拥有某些属性时,并非报错,而是把请求“转交”给它的原型对象处理。
看清两个关键角色的区别
很多人卡在第一步,是因为混淆了prototype和__proto__:
-
prototype是函数才有的普通属性,只存在于函数对象上(包括构造函数),它是一个对象,用来存放将来要被实例共享的方法和属性; -
__proto__(或Object.getPrototypeOf())是每个普通对象都有的内部链接,指向该对象“从哪来”——即创建它的构造函数的prototype对象; - 例如:
const p = new Person(),那么p.__proto__ === Person.prototype为真,这个等式就是原型继承成立的基石。
理解原型链的查找过程
当你写p.sayHello(),JS引擎不会直接去Person.prototype找,而是按固定路径一步步委托:
- 先查
p自身有没有sayHello; - 没有,就查
p.__proto__(也就是Person.prototype); - 还没找到,就继续查
Person.prototype.__proto__(即Object.prototype); - 再往上是
Object.prototype.__proto__,值为null,查找终止,返回undefined。
这个过程完全自动、不可跳过,且只读——你不能通过修改__proto__来“绕开”某一级,但可以重设整个链(需谨慎)。
立即学习“Java免费学习笔记(深入)”;
掌握手动构建原型链的方法
不依赖new也能实现继承,关键是控制[[Prototype]]的指向:
-
Object.create(proto):最干净的方式,直接让新对象的[[Prototype]]指向proto; -
Object.setPrototypeOf(obj, proto):运行时动态修改,但性能较差,仅用于调试或特殊场景; - 避免直接赋值
obj.__proto__ = proto,因非标准且影响优化。
比如:const dog = Object.create(animalPrototype),dog就天然能调用animalPrototype上的eat方法,无需任何构造函数。
注意 constructor 的隐含关系
每个prototype对象默认带一个constructor属性,指向其所属构造函数。这个关系不是强制的,但维护它能让代码更可读、调试更清晰:
- 如果你重写了
Dog.prototype = new Animal(),记得补上Dog.prototype.constructor = Dog,否则dog.constructor会指向Animal; - ES6 class 语法糖背后依然靠这套机制,
class Dog extends Animal最终生成的仍是基于__proto__和prototype的委托链。


















