为何Express内置中间件使用括号语法,自定义中间件却无需使用?
核心原因在于内置中间件是「工厂函数」,自定义中间件通常是直接的「中间件函数」,而app.use要求传入的必须是符合(req, res, next) => {}签名的中间件函数。
内置中间件如
express.json():
它本质是一个返回中间件函数的工厂函数,调用它(加括号)才会生成并返回真正处理请求的中间件。比如express.json()可以接收配置参数(如{ limit: '10mb' }),内部会根据配置生成对应的JSON解析逻辑,最终返回符合要求的中间件函数。如果不加括号,你传给app.use的是工厂函数本身,它不符合(req, res, next)的签名,程序会报错。自定义中间件如
logger:
你写的logger本身就是符合中间件签名的函数,比如:function logger(req, res, next) { console.log(`${req.method} ${req.path}`); next(); }直接把这个函数的引用传给
app.use即可。如果加括号写成app.use(logger()),相当于立即执行logger函数,若logger没有返回另一个中间件函数,就会把它的返回值(默认是undefined)传给app.use,而app.use无法识别非函数值,自然会抛出错误。
当然,自定义中间件也可以做成工厂函数的形式,比如需要配置的日志中间件:
function createLogger(options) { return function(req, res, next) { const logFn = options.level === 'debug' ? console.debug : console.log; logFn(`${req.method} ${req.path}`); next(); } }
这时候使用时就需要加括号:app.use(createLogger({ level: 'debug' })),和内置中间件的用法完全一致。
Express官方文档中对express.json()等内置中间件的描述会明确说明它们是「返回中间件函数的函数」,而app.use的文档也会明确它接收的是中间件函数,这就是语法差异的依据。
内容的提问来源于stack exchange,提问作者Sibasish Behera

