javascript原生不支持抽象类和接口,但可通过运行时检查(如new.target判断、throw错误)模拟抽象类,用对象约定+手动校验或typescript实现接口;ts提供abstract class和interface语法,支持多接口实现与抽象类组合使用。

JavaScript 原生不支持抽象类和接口的语法定义,但可以通过运行时检查 + 约定 + TypeScript 补充来模拟实现。关键不在“有没有关键字”,而在于“如何表达设计意图并保障契约”。
用运行时检查模拟抽象类
抽象类的核心特征是:不能被直接实例化,且必须有子类实现某些方法。JS 中可通过 new.target 和手动抛错达成:
- 在构造函数中判断
new.target === 当前类名,成立则说明正被直接 new,此时抛出错误 - 在方法体内用
throw new Error("抽象方法必须被重写")占位,强制子类覆盖 - ES6 class 示例:
constructor() {
if (new.target === Animal) {
throw new Error("Animal 是抽象类,不能直接实例化");
}
}
speak() {
throw new Error("speak 方法必须由子类实现");
}
}
用对象结构模拟接口(无运行时强制)
JS 没有 interface 关键字,所以“接口”本质是一份方法签名约定。常见做法是:
- 定义一个普通对象或函数,列出所有应实现的方法名(如
{ connect(), disconnect(), send() }) - 在子类中手动检查是否实现了这些方法(例如构造时遍历接口对象,确认 this 上存在对应方法)
- 更实用的做法是:不校验,靠文档 + 单元测试 + TypeScript 类型系统兜底
TypeScript 提供真正的抽象类与接口支持
若项目使用 TS,可直接用语言级特性,无需手动模拟:
-
abstract class:支持abstract方法、禁止 new 实例、子类必须实现抽象成员 -
interface:纯粹的行为契约,支持多实现(一个类可 implements 多个 interface) - 二者可组合:抽象类实现部分通用逻辑,interface 约束行为规范,子类同时
extends 抽象类 & implements 接口
继承链中的实际协作方式
真实开发中,抽象类与接口常配合使用:
- 抽象类负责共享状态、初始化逻辑、模板方法骨架(如
init() → doWork() → cleanup()) - 接口负责定义能力边界(如
Serializable、Disposable),与继承体系解耦 - 子类继承抽象类获得复用能力,同时实现接口表明它具备某类行为,便于类型判断和泛型约束











