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

JavaScript如何获取类自身声明字段(不含父类继承字段)

问题原因

你当前写法无法得到预期结果的核心原因是:JS类继承机制中,父类构造函数运行时的this直接指向子类创建的实例,父类里所有this.xxx = xxx的赋值操作,都会直接把属性挂载到子类实例上,成为实例的自有属性。因此直接对实例调用Object.getOwnPropertyNames(),会拿到父类、子类构造函数挂载的所有属性,无法直接区分属性归属。

实现方案

根据你是否可以修改原有类的代码,可选择以下两种实现方式:

  • 方案1:无需修改原有类定义,通用差集过滤法
    核心逻辑是先创建父类实例,拿到父类构造会挂载到实例上的全部属性,再创建子类实例取所有自有属性,过滤掉父类已存在的属性,剩下的就是子类自身声明的字段。

    class A {
      constructor() {
        this._a = 1;
      }
    }; 
    class B extends A {
      constructor() {
        super();
        this._b = 2;
      }
    };
    
    function getChildClassOwnFields(Child, Parent, ...initArgs) {
      // 拿到父类构造挂载的所有属性
      const parentIns = new Parent(...initArgs);
      const parentFieldSet = new Set(Object.getOwnPropertyNames(parentIns));
      // 子类实例属性过滤掉父类已存在的属性
      const childIns = new Child(...initArgs);
      return Object.getOwnPropertyNames(childIns).filter(field => !parentFieldSet.has(field));
    }
    
    console.log(getChildClassOwnFields(B, A)); // 输出: [ '_b' ]
    

    注意:该方案要求父类构造函数的属性挂载逻辑是稳定的,如果父类会根据入参、外部随机状态动态挂载不同属性,判断结果会出现偏差。

  • 方案2:可修改类定义时的精准获取法
    子类构造函数中,super()调用完成的瞬间,父类所有属性挂载逻辑已经全部执行完毕,此时子类自身的属性赋值还没开始,在这个节点快照实例上已有的属性,后续新增的属性就是子类100%自有的字段,不受父类动态逻辑影响。

    class A {
      constructor() {
        this._a = 1;
        // 模拟父类动态挂载属性的场景
        if (Date.now() % 2 === 0) this._randomA = 'dynamic';
      }
    }; 
    class B extends A {
      constructor() {
        super();
        // 快照父类挂载完成后的属性集合
        const parentFields = new Set(Object.getOwnPropertyNames(this));
        // 子类自身属性赋值
        this._b = 2;
        this._desc = 'class B';
    
        // 暴露获取自有字段的方法
        this.getOwnFields = () => {
          return Object.getOwnPropertyNames(this)
            .filter(field => !parentFields.has(field) && field !== 'getOwnFields');
        }
      }
    };
    
    const bIns = new B();
    console.log(bIns.getOwnFields()); // 永远输出 [ '_b', '_desc' ],不受父类动态属性干扰
    

    这个方案同样兼容ES6类实例字段(写在constructor外的字段声明)的场景,这类字段的初始化逻辑恰好是在super()执行后、constructor内代码执行前运行,会被自动归到子类自有字段中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:09:17