ES6中获取超类名称

20

我有一个类,还有另一个继承自该类的类。

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”)的名称?


1
foo.__proto__.constructor.name?我认为__proto__已经被标准化了,甚至。 - John Dvorak
2
这将为您提供一个父类,但不一定是对象直接扩展的那个类,也不是它最初扩展的那个类。 - joshstrike
谢谢Jan - 这让我再次得到了原始类,但是foo.proto.proto.constructor.name可以获取它。 - joelg
@joelg 是的,但如果你想进一步深入,你就必须不断地添加更多的 __proto__,然后当你到达 Object 时就会出现错误。你可能需要重新表述问题,如何获取父类。假设你的类不是最终类,子类将不会得到相同的结果。 - joshstrike
3
@JanDvorak:__proto__已经在Web浏览器的JavaScript引擎中标准化,仅作为向后兼容的事情。现代代码应该使用Object.getPrototypeOf - T.J. Crowder
4个回答

24
Object.getPrototypeOf(Object.getPrototypeOf(foo)).constructor.name;

6

明白了:

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

编辑:这会返回父类,但不一定是Circle最初继承的那个类。在我的用例中它们相同,但“超类”的含义存在微妙的歧义。


5
Object.getPrototypeOf__proto__更标准。Object.getPrototypeOf是官方推荐使用的方式来访问一个对象的原型,而__proto__虽然也能实现相同的功能,但不被官方推荐使用。 - loganfsmyth
1
那是直接的父类,不一定是你要找的超类。 - joshstrike
啊,谢谢。对我来说它们是一样的,但我可以看出这并不一定是情况。 - joelg
1
@joelg:__proto__仅为Web浏览器中的JavaScript引擎定义,纯粹是为了向后兼容,并不在所有对象上存在(尽管它存在于绝大多数对象上;基本上,使用o = Object.create(null)o没有__proto__属性,因为__proto__属性由Object.prototype定义,而o不使用)。Object.getPrototypeOf是获取对象原型的正确方法。 - T.J. Crowder
因为提问却没有真正听取回答而被踩。这个解决方案只适用于非常特定的情况,甚至不是一个好的解决方案。 - Russell Ormes

3
你可以定义以下类:
```html

你可以定义以下类:

```
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 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"));


-3

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

然而,您要问的是Shape在标准库或标准对象中分支的位置,编译器或运行时无法弄清楚。理论上,如果ECMA语言可以为给定类提供反向继承数组,那将非常好,但据我所知,这从未是一项功能。没有完整的继承链,您需要知道要查找的超类,否则无法以任何逻辑方式推导出它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接