原型链实现中间件队列的核心是共享原型上的调度逻辑而实例独立维护中间件数组;构造函数初始化this.stack,原型提供use添加、run递归执行(含错误中断与next闭包),不绑定this,统一fn(req, res, next)调用。

用原型链实现中间件队列,本质是把中间件函数存进实例属性,再通过原型上的方法统一调度执行。关键不是“继承”,而是让所有实例共享一套流程控制逻辑,同时各自维护独立的中间件列表。
构造函数与原型初始化
定义一个构造函数,内部初始化空数组用于存放中间件;所有执行逻辑(如添加、启动)都挂载在原型上,避免每次实例化重复创建函数。
- 构造函数只负责初始化状态(比如 this.stack = [])
- 原型上定义 use(fn):检查是否为函数,然后 push 进 stack
- 原型上定义 run(req, res):封装递归执行逻辑,不暴露 index 或 next 内部细节
执行流程基于闭包 + 原型方法
run 方法内部用闭包保存当前执行位置,每次调用 next 都是触发原型上预设的递归逻辑,而不是把 next 当作参数传给每个中间件——这样更贴近原生 Express 的设计语义。
- run 启动时,内部定义一个 dispatch(i) 函数,接收当前索引
- 若 i 超出 stack 长度,说明执行完毕,可触发 finalCallback 或直接返回
- 否则取出 this.stack[i],调用它并传入 req、res 和 () => dispatch(i + 1)
- 这个回调就是用户代码里写的 next(),它不依赖 this,也不污染中间件函数作用域
支持错误中断与透传
中间件常需处理异常,原型方法应兼容错误传递。可在 dispatch 中增加 err 判断,并提前终止后续执行。
- 中间件调用时允许传入 error(如 next(new Error('xxx')))
- dispatch 检查第一个参数是否为 Error 实例,是则跳过剩余中间件,直接调 finalCallback(err)
- 也可选择将 error 挂到 res 上(如 res.err = err),由最后的兜底中间件统一响应
避免 this 绑定混乱
中间件函数内部的 this 指向容易出问题。原型实现中,应明确不绑定 this,让中间件保持普通函数语义。
- 不要用 fn.call(this, ...) 或 fn.bind(this) 调用中间件
- 统一用 fn(req, res, next) 形式调用,语义清晰且符合主流约定
- 若需上下文,应通过 req/res 或闭包变量传递,而非依赖 this











