0

Given the example below, could someone please advise why is my C class show as anonymous? I'm trying to validate the instanceOf B.C and it's always false :(

Thank you in advance.

class A {
 constructor() {
   this.a = 1
 }
};

class B extends A {
 constructor() {
   super();
   this.a = 2;
 }
}

B.C = class extends B {
 constructor() {
   super();
   this.a = 3;
 }
}

console.log(A, B, B.C) //[class A], [class B extends A], [class (anonymous) extends B]

let test = new B.C();
console.log(test instanceof B.C) //false
console.log(test.constructor.name) //''
Constantin Suiu
  • 214
  • 2
  • 12

2 Answers2

2

In most situations, assigning an anonymous class expression to something (a variable, a property in an object initializer, the parameter name if using a class expression as the default value of the parameter, ...) assigns the name of the thing to the class. Example:

const A = class {};
console.log(A.name);          // "A"

const obj = {
    B: class {},
};
console.log(obj.B.name);      // "B"

function example(C = class {}) {
    console.log(C.name);      // "C"
}
example();

But there's a specific exception for when you're adding a property to an existing object. That was deemed a security risk by TC39 (imagine you're storing a class/function you're going to give to untrusted code using a key that should be private to your code and not exposed to theirs), so it's one of the very few places that doesn't happen:

const obj = {};
obj.A = class {};
console.log(obj.A.name); // ""

If you want B.C to have a name, give it one explicitly:

B.C = class SomeNameHere extends B {
    // ...

The same is true for anonymous function expressions, see my answer here for more on that.


In a comment on the answer you've said:

...However the instance validation is still showing as false. Any suggestions on what is causing this?...

That won't happen with the code in the question, regardless of whether B.C has a name. instanceof works just fine either way:

class A {
    constructor() {
        this.a = 1;
    }
}

class B extends A {
    constructor() {
        super();
        this.a = 2;
    }
}

// With a name
B.C = class BC extends B {
    constructor() {
        super();
        this.a = 3;
    }
};

// Without a name
B.D = class extends B {
    constructor() {
        super();
        this.a = 3;
    }
};

console.log(A, B, B.C); // [class A], [class B extends A], [class (anonymous) extends B]

let test = new B.C();
console.log(test instanceof B.C);   // true
console.log(test.constructor.name); // "BC"

let test2 = new B.D();
console.log(test2 instanceof B.D);   // true
console.log(test2.constructor.name); // ""
.as-console-wrapper {
    max-height: 100% !important;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks T.J. I now understand the anonymous issue. However the instance validation is still showing as false. Any suggestions on what is causing this? – Constantin Suiu Jun 08 '22 at 08:13
  • ok, I did some more tests and when I do console.log(test instanceof B.C) //false but console.log(test instanceof A) //true – Constantin Suiu Jun 08 '22 at 08:21
  • @ConstantinSuiu - The code you're actually doing that with must be different from the code in the question. The code in the question correctly reports `true` for `test instanceof B.C` (even if you don't add a name to the constructor), see the live example at the end of the answer. – T.J. Crowder Jun 08 '22 at 09:07
  • yes you are correct.. the actual code is a bit different, but it does the same.... I just have the base class coming from a module, then define my B/C classes in a file and send that instance of the classes to a class D where I do some validations. If I simulate that in a separate project it seems to work, but in my code the instance always returns true only for base class (A in the example). – Constantin Suiu Jun 08 '22 at 11:00
  • @ConstantinSuiu - You'll need to create a [mre] that actually replicates the problem. Start with your current problematic code and keep stripping things away until it stops breaking. See the link for details. – T.J. Crowder Jun 08 '22 at 17:17
0

Your last class is anonymus, becasue you never giving it the name C. You are just create a property called C containing the anonymus class.

I think the syntax for what you are expecting would look like this:

...

class C extends B {
 constructor() {
   super();
   this.a = 3;
 }
}

var B = new B();
B.C = new C();

In this way you are defining a new class called C and add a new property also called C to B and fill it with an instance of C.

Demian
  • 37
  • 3
  • The OP's code is clearly expecting `B.C` to be a class constructor, not an *instance* of the class. Note `let test = new B.C();` and `console.log(test instanceOf B.C)`. – T.J. Crowder Jun 08 '22 at 07:52
  • Thanks both for the reply. And yes, I do need B.C to be a constructor not an instance. Not sure how to solve this :( – Constantin Suiu Jun 08 '22 at 08:00