原型链本身不直接定义接口,但可通过构造函数+原型方法、Object.setPrototypeOf或class继承模拟接口行为,实现Mock对象具备约定方法并支持instanceof检查,但无法保证类型语义,需配合运行时断言或工具库使用。

原型链本身不直接定义接口,但可以借助其继承机制,配合构造函数或类,在 Mock 场景中模拟接口行为——核心是让 Mock 对象“看起来像”真实接口的实例,并能响应约定的方法调用。
用构造函数 + 原型方法模拟接口契约
假设有个用户服务接口 IUserService,约定有 getUser(id) 和 listUsers() 方法。不依赖 TypeScript 接口,而是通过原型统一挂载默认实现:
- 定义一个空构造函数(如
MockUserService),不执行实际逻辑 - 在
MockUserService.prototype上添加方法,返回预设数据或动态生成的假值 - 测试时 new 出实例,它就具备了接口要求的行为,且可被 instanceof 判断(例如
new MockUserService() instanceof IUserService可通过自定义检查逻辑模拟)
利用 Object.setPrototypeOf 实现运行时接口伪装
当需要临时让某个普通对象“表现得像实现了某接口”时,可手动设置其原型:
- 预先定义好一组 Mock 方法的对象字面量(如
mockUserMethods) - 用
Object.setPrototypeOf(mockObj, mockUserMethods)将其原型指向该行为集 - 后续调用
mockObj.getUser(123)就会沿原型链找到对应方法,无需修改原对象属性 - 适合插件化 Mock:不同场景切换不同原型,复用同一基础对象
结合 class 继承做分层 Mock 策略
真实项目中接口常有抽象基类(如 BaseApiService),Mock 时可继承并覆盖关键方法:
- 声明
class MockUserService extends BaseApiService - 只重写
fetch()或request()底层方法,返回 Promise.resolve(mockData) - 其余业务方法(如
getUserById)自动继承基类逻辑,保持调用链一致 - 这样既满足接口形态,又避免重复实现,也便于后期替换为真实网络请求
注意边界:原型链不能替代类型契约
原型链解决的是“行为存在性”和“动态委托”,但无法保证参数校验、返回结构、必选字段等接口语义:
- 建议配合简单断言(如
if (typeof obj.getUser !== 'function'))做运行时兜底 - 复杂场景推荐用工具库(如 MSW、MirageJS)接管请求层,原型 Mock 更适合作轻量单元测试或快速演示
- 不要试图用
__proto__模拟多继承;优先用组合或装饰器模式补足能力

















