
本文详解 TypeScript 类继承时因错误使用 new class 导致 this 丢失、方法调用报 TypeError: Cannot read properties of undefined 的根本原因及正确写法。
本文详解 typescript 类继承时因错误使用 `new class` 导致 `this` 丢失、方法调用报 `typeerror: cannot read properties of undefined` 的根本原因及正确写法。
在 TypeScript 中实现控制器类继承(如 SettingController extends BaseController)时,一个常见但极易被忽视的错误是:将子类声明为 export default new class ...——这会导致该“类”实际导出的是一个已实例化的对象字面量,而非可被 new 实例化的类构造器。其后果是:当 Express 路由直接引用该对象的方法(如 SettingController.SettingOTP)作为回调时,this 不再指向原实例,而是 undefined(严格模式下)或全局对象(非严格模式),从而在调用 this.Ok(...) 时触发 TypeError: Cannot read properties of undefined (reading 'Ok')。
? 根本原因分析
观察原始代码:
// ❌ 错误:导出的是一个立即实例化后的对象,不是类!
export default new class SettingController extends BaseController { ... }此时 SettingController 是一个单例对象,其原型链虽继承自 BaseController,但 SettingController.SettingOTP 被直接作为回调传入路由(settingRouter.put('/opt-setting', SettingController.SettingOTP)),此时该函数被以普通函数方式调用,this 绑定丢失。
使用 Scrapfly SDK(scrapfly-sdk)在 TypeScript 或 JavaScript 中进行网页抓取,用于用户请求抓取 URL、绕过反爬虫防护、渲染页面等场景。
而正确的做法是导出类本身,由使用者按需实例化(通常配合依赖注入),确保每次请求都能获得具备完整上下文的实例:
// ✅ 正确:导出类构造器,支持正常实例化与 this 绑定
export default class SettingController extends BaseController {
constructor(private readonly settingService: SettingService) {
super();
}
async SettingOTP(req: Request, res: Response, next: NextFunction) {
try {
// ...业务逻辑
return this.Ok(res, 'OTP setting updated successfully');
} catch (error: any) {
this.BadRequest(res, error.message); // 注意:原文中拼写为 BadRerquest,应为 BadRequest
}
}
}并在路由配置中显式创建实例(推荐结合 DI 容器):
import SettingController from '../../http/controller/SettingController';
import { SettingService } from '../../domain/service/SettingService';
const settingService = new SettingService();
const settingController = new SettingController(settingService); // ✅ 实例化
const settingRouter = express.Router();
settingRouter.put('/opt-setting', (req, res, next) =>
settingController.SettingOTP(req, res, next) // ✅ 箭头函数或绑定确保 this 正确
);
// 或更简洁地(利用 bind):
// settingRouter.put('/opt-setting', settingController.SettingOTP.bind(settingController));⚠️ 补充注意事项
-
避免箭头函数陷阱:若在类中将方法定义为箭头函数(如
SettingOTP = async (...) => { ... }),虽可固化this,但会破坏继承链中的super调用能力,且不符合 Express 中间件签名约定,不推荐。 -
修正拼写错误:答案中
BadRerquest应为BadRequest,请同步更新BaseController中对应方法名。 -
类型安全增强:建议为
BaseController的响应方法添加返回类型(如Ok<t>(res: Response, message: string): Response</t>),并确保SuccessResponse.send()明确返回res以支持链式调用。 -
生产环境建议:使用依赖注入框架(如 InversifyJS 或 NestJS 的内置 DI)管理控制器生命周期,避免手动
new实例。
通过回归标准类导出语法,并在路由层正确实例化与绑定,即可彻底解决 this.Ok is not a function 类型错误,保障继承体系的健壮性与可维护性。

















