javascript 通过约定和运行时检查模拟抽象类:在构造函数中用 new.target 判断并抛错阻止直接实例化,抽象方法体抛错并用 jsdoc @abstract 标注,子类须 extends、调用 super() 并重写抽象方法。

JavaScript 本身没有原生的抽象类语法,但可以通过约定、运行时检查和继承机制来有效模拟抽象类的行为——核心是阻止直接实例化基类,并强制子类实现特定方法。
用构造函数抛出错误来禁止直接实例化
在抽象基类的 constructor 中判断是否被直接调用(而非通过子类 super() 调用),如果是就抛出错误:
class Animal {
constructor() {
if (new.target === Animal) {
throw new Error('Animal 是抽象类,不能直接实例化');
}
}
speak() {
throw new Error('子类必须实现 speak 方法');
}
}这里 new.target 指向当前构造函数。若直接 new Animal(),new.target === Animal 成立;而子类调用 super() 时,new.target 是子类构造器,不会触发错误。
用方法体抛错 + JSDoc 标注明确抽象意图
抽象方法不提供具体实现,只抛错,并配合 JSDoc @abstract 标签提升可读性和工具支持(如 VS Code 提示、TypeScript 类型检查):
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
/**
* @abstract
* @returns {string}
*/
speak() {
throw new Error('speak() 必须由子类实现');
}这样既让运行时有兜底保护,又让开发者在编码阶段就能意识到该方法需重写。
结合 extends 和 super() 确保子类正确继承
子类必须显式调用 super(),否则会报错;同时可在子类中覆盖抽象方法:
- 子类定义时必须使用
extends Animal - 子类 constructor 中必须调用
super()(哪怕只是空调用) - 子类需重写所有标记为抽象的方法,否则调用时才会暴露问题
class Dog extends Animal {
constructor(name) {
super(); // 必须调用
this.name = name;
}
speak() {
return `${this.name} 汪汪!`;
}
}
console.log(new Dog('旺财').speak()); // ✅ 正常输出进阶:用 Symbol 或私有字段增强抽象契约
如果想进一步防止子类绕过抽象约束,可用唯一 Symbol 作为“抽象标记”,或用私有字段配合 getter 检查:
- 定义
const ABSTRACT = Symbol('abstract'),在基类中设置this[ABSTRACT] = true - 子类构造后检查
this[ABSTRACT]是否仍存在,存在则说明未正确初始化 - 更实用的做法是:在基类关键方法中检查子类是否已定义必需属性或方法,例如
if (typeof this.speak !== 'function') throw...
这类技巧适合对抽象契约要求严格的场景,但多数情况下前三种方式已足够清晰可靠。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










