javascript原型链继承本质是子类实例通过[[prototype]]链访问父类prototype上的属性和方法,实现共享复用;核心靠构造函数、prototype和__proto__协同,child.prototype=new parent()构建链路,需修正constructor,注意引用类型属性共享缺陷,终点为object.prototype([[prototype]]为null)。

JavaScript 中基于原型链的面向对象继承,本质是让子类实例能顺着 [[Prototype]] 链访问到父类定义的属性和方法,从而实现共享与复用。它不依赖“类”的语法糖,而是靠构造函数、prototype 和实例的隐式原型 __proto__ 三者协同完成。
核心机制:原型对象作为共享池
每个函数(非箭头函数)默认拥有 prototype 属性,它是一个普通对象,初始含一个 constructor 指向自身。当你用 new Parent() 创建实例时,该实例的内部 [[Prototype]](可通过 Object.getPrototypeOf() 或非标准 .__proto__ 访问)会自动指向 Parent.prototype。
所以,把父类的方法写在 Parent.prototype 上,所有通过 new Parent() 创建的实例都能访问——不是拷贝,而是引用同一份函数体,节省内存。
实现继承:子类原型 = 父类实例
要让子类也复用父类原型上的方法,只需让 Child.prototype 指向一个父类实例:
-
关键一步:执行
Child.prototype = new Parent(); - 此时,
Child的所有新实例(如const c = new Child())的[[Prototype]]指向Child.prototype,而后者又指向Parent.prototype,形成一条链:c → Child.prototype → Parent.prototype → Object.prototype → null -
必须修正 constructor:因为
new Parent()返回的对象其constructor指向Parent,不是Child,所以需手动设置Child.prototype.constructor = Child;,否则c.constructor会误判
方法复用与属性隔离的关键区别
原型链天然适合复用方法,但对构造函数中定义的实例属性要格外注意:
-
方法安全复用:写在
Parent.prototype上的方法(如sayName()),被所有子类实例共享且互不影响 -
引用类型属性慎用:若
Parent构造函数里写了this.colors = ['red'],那么所有子类实例会共享这个数组——修改c1.colors.push('blue'),c2.colors也会变。这是原型链继承的典型缺陷 -
基本类型属性可读不可写:若
Parent中有this.name = 'parent',子类实例读取时会从原型链上拿到值;但一旦执行c1.name = 'child1',就在自身创建了同名属性,屏蔽了原型上的值,后续读取走的是实例自身
为什么 Object.prototype 是终点
所有原型链最终都会到达 Object.prototype,因为它是 JavaScript 中绝大多数对象的顶层原型。它的 [[Prototype]] 明确为 null,表示查找终止。这也是为什么所有对象都能调用 toString()、hasOwnProperty() 等方法——它们定义在 Object.prototype 上,沿链向上可达。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











