【问题标题】:Get superclass name in ES6在 ES6 中获取超类名称
【发布时间】:2019-10-11 06:22:15
【问题描述】:

我有一个类,以及扩展该类的另一个类。

class Shape {
  constructor() {
    return this;
  }
}
class Circle extends Shape {
  constructor() {
    super();
    return this;
  }
}
let foo = new Circle();

我可以得到 foo 的课程

let className = foo.constructor.name 
// returns string 'Circle'

是否有可能以类似的方式获取 foo 的超类('Shape')的名称?

【问题讨论】:

  • foo.__proto__.constructor.name?我认为__proto__ 已经标准化了,甚至。
  • 这会给你一个父类,但不一定是对象直接扩展的类,或者它最初扩展的类。
  • 谢谢 Jan - 这又给了我原来的课程,但是 foo.__proto__.__proto__.constructor.name 得到了它。
  • @joelg 是的,但如果你想更进一步,你必须继续向它添加更多 proto,然后当你点击 Object 时会出现错误。您可能想重新表述有关如何获取父类的问题。假设您的课程不是最终课程,则子课程不会得到相同的结果。
  • @JanDvorak: __proto__ 仅针对 Web 浏览器中的 JavaScript 引擎进行了标准化,纯粹是为了向后兼容。现代代码应该使用Object.getPrototypeOf

标签: javascript ecmascript-6


【解决方案1】:
Object.getPrototypeOf(Object.getPrototypeOf(foo)).constructor.name;

【讨论】:

    【解决方案2】:

    知道了:

    let superClassName = foo.__proto__.__proto__.constructor.name
    // return Shape
    

    编辑:返回父类,不一定是原来扩展的类Circle。在我的用例中,它们是相同的,但这里的“超类”的含义存在微妙的歧义。

    【讨论】:

    • Object.getPrototypeOf 会比 __proto__ 更标准。
    • 这是直接父类,不一定是您要查找的超类。
    • 啊,谢谢。它们对我来说是一样的,但我可以看到情况不一定如此。
    • @joelg: __proto__ 仅针对 Web 浏览器中的 JavaScript 引擎定义,纯粹是为了向后兼容,并不存在于所有对象上(尽管它存在于 绝大多数 对象;基本上,对于o = Object.create(null)o 没有__proto__ 属性,因为__proto__ 属性由Object.prototype 定义,o 不使用)。 Object.getPrototypeOf是获取对象原型的正确方法。
    • 投了反对票,因为提出了一个问题,但没有真正倾听他们的回答。此解决方案适用于非常具体的情况,甚至不是一个好的解决方案
    【解决方案3】:

    您可以定义以下类:

    class MyObject
    {
      extends(className)
      {
        let next = Object.getPrototypeOf(this);
    
        while(next.constructor.name !== "Object")
        {
          if(next.constructor.name === className)
            return true;
          next = Object.getPrototypeOf(next);
        }
        return false;
      }
    }
    

    让您定义的每个类都扩展该类。

    现在如果你想检查你的对象是否扩展了一个特定的类,你可以调用它的 extends 方法并将父类的名称作为参数传递。 extends 方法将遍历整个继承树并检查您的对象是否扩展了给定的类,不仅检查他的父母,还检查他的祖父母和祖父母等等。

    例子:

    class MyObject
    {
      extends(className)
      {
        let next = Object.getPrototypeOf(this);
    
        while(next.constructor.name !== "Object")
        {
          if(next.constructor.name === className)
            return true;
          next = Object.getPrototypeOf(next);
        }
        return false;
      }
    }
    
    class Vehicle extends MyObject
    {
    }
    
    class Car extends Vehicle
    {
    }
    
    class Bmw extends Car
    {
    }
    
    let car = new Car();
    let bmw = new Bmw();
    
    console.log("bmw extends Bmw: " + bmw.extends("Bmw"));
    console.log("bmw extends Car: " + bmw.extends("Car"));
    console.log("bmw extends Vehicle: " + bmw.extends("Vehicle"));
    console.log("car extends Car: " + car.extends("Car"));
    console.log("car extends Bmw: " + car.extends("Bmw"));

    【讨论】:

      【解决方案4】:

      您的最终超类始终是 Object,因此没有必要尝试派生它。您需要使用 'is' 关键字来探测有问题的实例是否是其他东西的实例。我是从 Actionscript-3 的角度来写这篇文章的,所以我不确定 ES-6 中的语法到底是什么,但它应该遵循“if (this is Shape)”这一行。如果有问题的实例扩展了您正在谈论的类,则返回 true,否则返回 false。

      但是,您要问的是 Shape 从标准库或标准 Object 分支的位置,编译器或运行时无法弄清楚这一点。从理论上讲,如果 ECMA 语言可以为您提供给定类的向后继承数组,那将是非常好的,但 AFAIK 不是而且从来都不是一个特性。如果没有完整的继承链,您需要知道要查找的超类,否则无法以任何合乎逻辑的方式派生它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-07
        • 1970-01-01
        • 2011-03-25
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 1970-01-01
        相关资源
        最近更新 更多