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

TypeScript中this.method与super.method差异及跨项目调用异常解析

问题:TypeScript继承中this调用父类方法在不同项目中表现差异的原因

类继承结构

export class BaseClass {
  public getDevice() {
  }
}

export class InheritClass extends BaseClass {
  constructor() {
    super();
  }
  public devices() {
   // this.getDevice() // 在Next.js项目中可用,但在Express项目中为undefined
   // super.getDevice() // 在两个项目中均可用
  }
}

现象说明:子类InheritClass的devices方法中,通过this.getDevice()调用父类方法时,在Next.js项目中正常,但在Express项目里this.getDevice为undefined;而用super.getDevice()在两个项目中都能正常执行。

两个项目的tsconfig.json配置

Express项目

"target": "ES2018",
"module": "commonjs",
"lib": ["es6", "dom"],

Next.js项目

"target": "esnext",
"lib": [
  "dom",
  "dom.iterable",
  "esnext"
],
"module": "esnext",

Express项目中的额外相关代码(中间件类)

import { injectable } from 'inversify';
import "reflect-metadata";
import { Request, Response, NextFunction } from "express";
import rateLimit from 'express-rate-limit';
import { ResponseData } from "@/interface/responseData";
import { generalMsg } from "@/msg";

@injectable()
export class BaseMiddleware {
  private limiter = rateLimit({
    windowMs: 1 * 60 * 1000, // 限制1分钟
    max: 1000, // 1分钟内最多1000次请求
  });
  public async execute(req: Request, res: Response, next: NextFunction): Promise<void | {}> {
    try {
      this.limiter(req, res, () => {
        next();
      });
    } catch (error) {
      console.error(error);
    }
  }
  protected badRequest(error: {details: any}, res: Response){
    const responseData = new ResponseData(
      null,
      generalMsg.error.request,
      false,
      error.details
    );
    return res.status(400).json(responseData.toJson());
  }
}

import "reflect-metadata";
import { injectable } from "inversify";
import { Request, Response, NextFunction } from "express";
import Joi from "joi";
import { BaseMiddleware } from "@middleware/base.middleware";

@injectable()
export class DeviceMiddleware extends BaseMiddleware {  
  constructor() {
    super();
  }
  public async addDevice(
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void | {}> {
    try {
      const schema = Joi.object({
        userId: Joi.number().allow(null),
        deviceToken: Joi.string().required(),                
      });
      const validateSchema = await schema.validateAsync(req.body);
      next();
    } catch (error: any) {
      if (error) {
        return super.badRequest(error, res);
      }
    }
  }
}

原因分析

  1. 模块编译与输出差异

    • Next.js采用ESNext模块系统,TypeScript编译后保留原生ES6+类的继承逻辑,子类实例的this能正确指向自身,自然可以通过原型链访问到父类的getDevice方法。
    • Express采用CommonJS模块系统,TypeScript将ES类编译为CommonJS风格的构造函数实现,这种编译方式下类的原型链绑定逻辑与原生ES类存在差异,容易为this指向异常埋下隐患。
  2. Inversify装饰器的影响
    Express项目中的类都使用了@injectable()装饰器,Inversify在处理这些类时,会修改类的构造逻辑或创建实例代理,打乱了子类实例的this上下文。此时this.getDevice()中的this并非指向子类实例,因此无法找到父类方法;而super.getDevice()是直接调用父类原型上的方法,绕过了this指向的问题,因此在两个项目中都能正常工作。

  3. 方法访问方式的本质区别

    • this.getDevice()依赖于this的指向,只有当this正确指向子类实例时,才能通过原型链找到父类的方法。
    • super.getDevice()是直接引用父类原型的方法,不依赖当前this的上下文,因此不受环境差异影响。

内容的提问来源于stack exchange,提问作者Hai Tien

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:07:48