Search code examples
javascriptecmascript-6classname

How do I change the constructor name of class expression after its definition?


Popular approach for faking namespace hierarchy:

class Stem {};
Stem.Branch = class extends Stem {};
Stem.Branch.Twig = class extends Stem.Branch {};
Stem.Branch.Twig.Leaf = class extends Stem.Branch.Twig {};

Let's do some introspection of an instance. The following has the "wrong"/unintended result (probably it climbs until it finds a name):

» (new Stem.Branch.Twig).constructor.name
"Stem"

I am allowed to attach a name to the class expression:

Stem.Branch.Twig = class Stem.Branch.Twig extends Stem.Branch {};

but this is a syntax error, identifiers can't contain dots, and quoting does not help. Without dots, it at least works for humans, but is rather useless for computers:

Stem.Branch.Twig = class StemBranchTwig extends Stem.Branch {};
» (new Stem.Branch.Twig).constructor.name
"StemBranchTwig"

I want to mess with the class name after its definition, so that the constructor name of an instance shows as I desire, but I can't figure out how.


Solution

  • function assign_name(moniker) {
        eval(`Object.defineProperty(${moniker}, 'name', {value: '${moniker}'});`);
    }
    
    class Stem {};
    
    Stem.Branch = class extends Stem {};
    assign_name('Stem.Branch');
    
    Stem.Branch.Twig = class extends Stem.Branch {};
    assign_name('Stem.Branch.Twig');
    
    Stem.Branch.Twig.Leaf = class extends Stem.Branch.Twig {};
    assign_name('Stem.Branch.Twig.Leaf');
    
    » (new Stem.Branch.Twig).constructor.name
    "Stem.Branch.Twig"