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

如何判断JavaScript基类方法是否被子类通过super.method()调用?

如何判断基类中的方法是否被直接调用?

假设存在如下代码:

class Base {
    myMethod() {}
}

class Child1 extends Base {
    myMethod() {}
}

class Child2 extends Base {
    myMethod() {
        super.myMethod();
    }
}

class Child3 extends Base {}

// extending another Child
class Child4 extends Child2 {}

需求

若子类或其除Base外的父类未实现该方法,则从Base.myMethod中抛出错误,具体表现如下:

let c1 = new Child1();
c1.myMethod(); // Method found on instance, works

let c2 = new Child2();
c2.myMethod(); // Method found on instance, calls super method (on Base), works

let c3 = new Child3();
c3.myMethod(); // No method found on instance, Base class throws an error

let c4 = new Child4();
c4.myMethod(); // No method found on instance but is found on parent (Child2), thus works

简言之:仅当Base的myMethod被直接调用(调用栈中无super.myMethod())时抛出错误,该如何实现这一判断?


解决方案

推荐通过遍历实例的原型链,判断首个拥有myMethod的原型对象是否为Base.prototype,这种方式兼容性强且逻辑可靠。

修改Base类的myMethod如下:

class Base {
    myMethod() {
        let currentProto = Object.getPrototypeOf(this);
        // 向上遍历原型链,找第一个自身定义了myMethod的对象
        while (currentProto) {
            if (currentProto.hasOwnProperty('myMethod')) {
                // 若找到的不是Base的原型,说明有子类实现了方法,正常执行
                if (currentProto !== Base.prototype) {
                    return;
                }
                // 否则就是直接调用基类方法,抛出错误
                break;
            }
            currentProto = Object.getPrototypeOf(currentProto);
        }
        throw new Error('Method must be implemented by a subclass');
    }
}

原理说明

  • 调用myMethod时,从当前实例的原型开始向上遍历原型链
  • 找到第一个自身拥有myMethod属性的原型对象:
    • 若该对象不是Base.prototype,说明存在子类(或子类的子类)实现了方法,即使通过super调用过来也允许执行
    • 若该对象就是Base.prototype,说明没有任何子类实现该方法,属于直接调用基类方法,抛出错误

测试后完全符合需求:

  • Child1实例调用:找到Child1.prototype的myMethod,正常执行
  • Child2实例调用:找到Child2.prototype的myMethod,正常执行(即使调用了super)
  • Child3实例调用:遍历到Base.prototype才找到方法,抛出错误
  • Child4实例调用:遍历到Child2.prototype的myMethod,正常执行

另外也可以通过调用栈判断(兼容性稍差,依赖浏览器调用栈格式):

class Base {
    myMethod() {
        const stack = new Error().stack;
        // 检查调用栈中是否存在super.myMethod的调用痕迹
        if (!stack.includes('super.myMethod')) {
            throw new Error('Method must be implemented by a subclass');
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:50:14