You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express中间件报错:TypeError: 无法向未声明#nextId的对象写入私有成员

问题分析与解决方案

你推测的完全正确——这个错误就是this上下文丢失导致的。当你直接把logger.setupMiddleware传给server.use时,Express调用该函数时,this并不会指向你的Logger实例,而是变成了默认上下文(严格模式下是undefined),自然无法访问类的私有成员#nextId。

下面是几种直接有效的解决方法:

方法1:用bind手动绑定this

在main.js中修改中间件的引用,通过bind把this固定指向logger实例:

server.use(logger.setupMiddleware.bind(logger));
// 其他涉及私有成员的中间件也需要同样处理
server.use(logger.startMiddleware.bind(logger));
server.use(logger.endMiddleware.bind(logger));

bind会返回一个新函数,该函数执行时this始终指向logger实例,就能正常访问私有成员了。

方法2:将中间件定义为箭头函数

在logger.js里,把需要作为中间件的方法改成箭头函数——箭头函数的this会继承自类实例的上下文,不会丢失:

const logger = new class Logger {
   #nextId = 0;
   // 改为箭头函数
   setupMiddleware = (req, res, next) => {
        if (!fs.existsSync(logFilename))
            this.#nextId = 0;
        next();
   };

   startMiddleware = (req, res, next) => {
       // 你的逻辑
       next();
   };

   endMiddleware = (req, res, next) => {
       // 你的逻辑
       next();
   };
}
module.exports = logger;

这种写法最简洁,之后main.js里的代码无需修改,直接使用server.use(logger.setupMiddleware)即可。

方法3:在构造函数中提前绑定this

如果偏好使用普通函数,可以在类的构造函数里提前完成this绑定:

const logger = new class Logger {
   #nextId = 0;

   constructor() {
       // 绑定所有需要作为中间件的方法
       this.setupMiddleware = this.setupMiddleware.bind(this);
       this.startMiddleware = this.startMiddleware.bind(this);
       this.endMiddleware = this.endMiddleware.bind(this);
   }

   setupMiddleware(req, res, next) {
        if (!fs.existsSync(logFilename))
            this.#nextId = 0;
        next();
   }

   startMiddleware(req, res, next) {
       // 你的逻辑
       next();
   }

   endMiddleware(req, res, next) {
       // 你的逻辑
       next();
   }
}
module.exports = logger;

这种方式下,main.js的代码也不需要调整,直接使用原写法即可。

内容的提问来源于stack exchange,提问作者Sus Amongus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:02:07