-2

In JavaScript (ES6), how do I programmatically get the name of the super class, in which the "current" code is executed?

Example:

class MySuperClass {
   logName() {
     console.log(this.XXX()); // always logs "MySuperClass"
   }
}

class MySubClass extends MySuperClass {
   logName() {
      super.logName();
      console.log(this.XXX()); // always logs "MySubClass"
   }
}

class MySubSubClass extends MySubClass {
   logName() {
      super.logName();
      console.log(this.XXX()); // always logs "MySubSubClass"
   }
}

const subSubClass = new MySubSubClass();

console.log(subSubClass);

Expected result from this code would be:

MySuperClass
MySubClass
MySubSubClass

What do I need to do instead of this.XXX()?

Note that I do not want to hard-code the name of the classes as string constants. I want a way that gets the "current" class name programmatically, as the flow trickles up the class tree.

Possible?

What does NOT work is this.constructor.name - it always returns the "lowest" inherited constructor name, in this case, it would yield "MySubSubClass" in all 3 levels.

Edit: One kind of hacky way would be to throw an exception on purpose and parse the stack string to see in which file / class the exception was thrown. But ugh! Is there no clean way?

blitter
  • 334
  • 2
  • 17
  • 1
    Separately, this feels a bit like an [X/Y problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What would you do with this information if you had it? – T.J. Crowder May 24 '22 at 17:16
  • @T.J.Crowder `this.XXX()` is the construct that the successful answer needs to give me. It's a placeholder for "please tell me what I should use instead of `this.XXX()` to get the class name I want". Perhaps I mean "what prototype the method that's currently running is on". I appreciate your observations, but in general, responses of the kind "but why would you ever want to do this?" are not helpful. Instead of making me wrong for wanting something, could we focus on the solution, please? :) – blitter May 24 '22 at 17:17
  • 2
    Asking *why* and pointing out the X/Y thing we **all** do sometimes is not suggesting you're "wrong," and "why would you ever want to do this" is not **remotely** an accurate rephrasing of what I asked above. – T.J. Crowder May 24 '22 at 17:29
  • You can get the superclass’s name with `super.constructor.name`, which is sort of close. – Ry- May 24 '22 at 17:34
  • *Perhaps I mean "what prototype the method that's currently running is on"* – the way to do that would be `[class name].prototype`, so this is why knowing the purpose is helpful. – Ry- May 24 '22 at 17:36
  • @Ry- I want an agnostic solution, i.e. the class in which the code lives should not know anything about its super or sub classes, should not traverse the tree, should not refer to its super, etc. IIRC, `Object.getPrototypeOf(this)` refers to the same target object, as `this.constructor.name`, `this`, i.e. the best I'll get is the name of `MySubSubClass` in my example. So that won't work, if I am understanding things correctly. What I want is 100% defined in my example. Why I want it? Let's say for debugging or whatever. It should make no difference. – blitter May 24 '22 at 17:45
  • I said `super.constructor.name`, not `this.constructor.name`. – Ry- May 24 '22 at 17:47
  • @Ry- I know you referred to `super.constructor.name` but that's not a solution because `super.constructor.name` looks "from the outside (subclass) into a superclass". What if there is no superclass? I want agnostic code that doesn't know or care if the class is used currently in an inheritance tree or not. While `super.constructor.name` can sort of solve the problem in other situations, as you acknowledged, it doesn't solve my question. – blitter May 24 '22 at 17:50
  • 2
    A single keyword to reference the containing class (something like `this.class`) doesn’t exist in JavaScript. (It’s not really necessary when you can store and reference it in arbitrary names in scope.) Does that answer your question, or do you have a motivating problem you’re trying to solve that would benefit from people proposing alternative solutions? – Ry- May 24 '22 at 17:53
  • I guess if you’re considering parsing an exception stack, manually traversing the prototype chain with `Object.getPrototypeOf` and comparing the parent prototype with `super.constructor.prototype` would be preferable? (This still doesn’t work by default when there’s no prototype – you would have to catch the exception from accessing `super.constructor` – but are you aware that `Object.prototype` is the default? A class with a `null` prototype is rare, and that’s not the only obscure situation that can break things.) It’s really much cleaner to write `[class name].constructor.name`, though. – Ry- May 24 '22 at 18:01
  • @Ry- `[class name].constructor.name` as in `MySubClass.constructor.name`? It would make sense if it worked that way, but it yields the string `Function` IIRC. – blitter May 24 '22 at 18:09
  • @blitter: Sorry, `[class name].name` rather – yes, like `MySubClass.name`. – Ry- May 24 '22 at 18:09
  • @Ry- Looks like traversing and such is inevitable. If you or anyone wrote code that traverses or does whatever, so long as it gives the desired class name of that inheritance level, I would accept that answer, of course. – blitter May 24 '22 at 18:24
  • @Ry- `[class name].name` like `MySubClass.name` is the only construct that works, thank you! I didn't know this was possible. If you post this as the solution, I'll accept it! Thank you! – blitter May 24 '22 at 22:16

0 Answers0