用经典构造函数配合prototype实现原型继承,关键在于让子构造函数的prototype指向父构造函数的一个实例并修正constructor指针;需用new Parent()或Object.create(Animal.prototype)设置原型链,避免直接赋值导致共享,再手动修复constructor,子类中用Parent.call(this)初始化实例属性。

用经典构造函数配合 prototype 实现原型继承,关键在于让子构造函数的 prototype 指向父构造函数的一个实例,并修正 constructor 指针。这种方式模拟“类式继承”,适合需要多次创建实例、且希望方法复用的场景。
设置子类原型为父类实例
这是核心步骤:把子构造函数的 prototype 替换为父构造函数的新实例,使所有子类实例能沿原型链访问父类方法。
- 不能直接赋值
Child.prototype = Parent.prototype,否则会共享同一原型对象,修改会影响父类 - 正确做法是
Child.prototype = new Parent(),这样子类原型拥有父类实例的全部属性和方法(包括从Parent.prototype继承来的) - 注意:父类构造函数中定义的引用类型属性(如数组、对象)会被所有子类实例共享,需谨慎处理
修复 constructor 指向
执行 new Parent() 后,Child.prototype.constructor 会指向 Parent,导致实例的 constructor 不准确。
- 手动重设:
Child.prototype.constructor = Child - 或使用
Object.defineProperty配置writable: false,更符合原生行为 - 不修复会导致
instance.constructor === Parent,影响 instanceof 判断和反射逻辑
在子类原型上添加自有方法
父类方法已通过原型链继承,子类可继续在其 prototype 上扩展专属功能。
- 新增方法写在
Child.prototype上,例如:Child.prototype.sayHi = function() { ... } - 避免覆盖父类同名方法时意外丢失,可用
super思路手动调用:Parent.prototype.methodName.call(this, ...) - 若需初始化父类实例属性(如
this.name),应在子构造函数内用Parent.call(this, ...),防止原型上引用类型被共享
完整示例结构
一个典型实现包含三部分:父构造函数定义、子构造函数定义、原型链连接与修正。
- 父类:
function Animal(name) { this.name = name; },并在Animal.prototype添加eat方法 - 子类:
function Dog(name, breed) { Animal.call(this, name); this.breed = breed; } - 继承:
Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; - 扩展:
Dog.prototype.bark = function() { console.log('Woof!'); };

















