JavaScript中普通函数父类的继承需分两步:先用call/apply实现构造函数继承(确保实例属性独立),再用Object.create(Father.prototype)实现原型方法继承(并修复constructor),且不可直接用class extends普通函数。

当父类是普通函数(非 class 语法定义)时,JavaScript 中的继承仍可实现,但需明确区分“构造函数继承”和“原型方法继承”两步,并注意 this 指向与属性共享问题。
用 call/apply 在子构造函数中继承父类实例属性
父函数若设计为构造函数(内部使用 this 赋值),可在子构造函数中用 call 或 apply 将其 this 绑定到子实例上,从而让子实例拥有独立的属性副本:
- 避免引用类型属性被所有实例共享(如数组、对象)
- 支持向父函数传参,提升灵活性
- 示例:function Father(name) { this.name = name; this.hobbies = ['reading']; }
function Son(name, age) { Father.call(this, name); this.age = age; }
通过原型链继承父类的方法
父函数的公共方法应挂载在其 prototype 上,子类再将自身 prototype 指向父类的一个新实例(或用 Object.create),完成方法复用:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 不推荐直接赋值 Son.prototype = new Father(),否则会执行父构造函数并可能引发副作用
- 更安全的做法是 Son.prototype = Object.create(Father.prototype)
- 必须手动修复 constructor: Son.prototype.constructor = Son,否则 instanceof 和构造器识别会出错
注意 this 的实际指向取决于调用方式
父函数内部的 this 不由定义位置决定,而由执行时的调用上下文决定:
立即学习“Java免费学习笔记(深入)”;
- 用 new Father() 调用 → this 指向新创建的实例
- 用 Father() 直接调用(非严格模式)→ this 指向全局对象(如 window)
- 用 Father.call(obj) → this 指向 obj
- 作为对象方法调用(如 obj.method = Father; obj.method())→ this 指向 obj
不建议混合使用 class 和函数父类
ES6 class 是语法糖,其 extends 要求父类可被 new 调用且具有 Symbol.hasInstance 方法。若父类是简单函数(未适配 class 规范),直接写 class Son extends Father 会报错:
- TypeError: Class extends value [Function: Father] is not a constructor
- 此时应放弃 extends,改用上述构造函数 + 原型链的手动继承方案
- 若必须用 class 子类,可包装父函数为兼容构造器,例如返回一个带 prototype 的函数对象

















