0

Different ways of defining, but what's the difference?

class A {}

const B = class {}

const C = class {
    static define() {
        /* do some code */

        return this // the class itself, as it is a static method
    }
}.define()

I would expect the problem to be in B and C then A to just work, but A and B works fine, and C just doesn't.

When I log them, I get the classes. But if I log their name property:

class A {}

const B = class {}

const C = class {
    static define() {
        /* do some code */

        return this // the class itself, as it is a static method
    }
}.define()

console.log('A -', A.name) //output: "A - A"
console.log('B -', B.name) //output: "B - B"
console.log('C -', C.name) //output: "C -"

I'm bit confused. If const holds just the value (class), how does it give a name. Or if it's variable's name or something similar, why wouldn't it work with a returned value in C then?

I tried to research but couldn't find an article. Then I made tests. Results were unexpected (they're included in the question). I expect someone to explain what is going on here. It's a really subtle thing. But the class is treated like an anonymous class in one way, and the other is like a normal class, which I didn't expect to be. The classic way works just fine, but this, I really wonder this.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
FLAW
  • 307
  • 2
  • 12
  • Your question doesn't match the title; you seem to be asking about differing behaviour between two forms of [class expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/class) **not** the difference between that and a [class statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class). – jonrsharpe Nov 06 '22 at 11:53
  • yeah you are right. I've changed the title. – FLAW Nov 06 '22 at 11:54
  • @jonrsharpe I couldn't find an explanation for `C` in your links. But yes, it's more about classes than modules. – FLAW Nov 06 '22 at 12:00
  • Your title still doesn't match, the examples you seem to be contrasting (B and C) _both_ use `const X = class` syntax (the expression not the statement). – jonrsharpe Nov 06 '22 at 12:02
  • @jonrsharpe it matches the examples `B.name` returns `'B'` for me, but `C.name` returns `''` – Konrad Nov 06 '22 at 12:05
  • 1
    This should answer the question [How do I write a named arrow function in ES2015?](https://stackoverflow.com/questions/27977525/how-do-i-write-a-named-arrow-function-in-es2015) – Konrad Nov 06 '22 at 12:08
  • @KonradLinkowski right, but they're _both anonymous class expressions_, neither uses the `class X {}` syntax the title refers to. A doesn't actually seem to be relevant to the question. – jonrsharpe Nov 06 '22 at 12:10
  • We should change the title then – Konrad Nov 06 '22 at 12:12
  • 1
    "*A and B works fine, and C just doesn't.*" - what's the problem? `C` works as well, I don't get a syntax error or anything. – Bergi Nov 06 '22 at 13:39

1 Answers1

0

I guess that the second syntax is in fact more like this:

const C = (() => class {})()
console.log(C.name)

That's why js engine can't determine function's name

How to fix it based on that answer?

const C = (() => class {})()
Object.defineProperty(C, 'name', {
  value: 'C'
});
console.log(C.name)

const C = class {
    static define() {
        return this
    }
}.define()
Object.defineProperty (C, 'name', {value: 'C'});
console.log(C.name)
Konrad
  • 21,590
  • 4
  • 28
  • 64
  • That's exactly what I thought. But `B` working just confused me. now I understood. Is there a way to make `C` work? Or I can't export a programatically made class? – FLAW Nov 06 '22 at 12:26
  • 1
    @FLAW this seems like a code smell: I can't think of any *good* reason code will rely on the `name` property of a class. There are, however, plenty of *bad* reasons that will make the code brittle and unreliable. As your code seems to be if you require a way to patch over the lack of `name`. At its core, you shouldn't have to rely on unreliable information. Note that even if you patch over the `name` property, then you have *further problems* - classes can have *the same name*. If you rely on the names being there, I suspect duplicate names would also be an issue. – VLAZ Nov 06 '22 at 12:37
  • @VLAZ it wasn't only about the `name`, but I was scared cuz it looks like `B` and `C` isn't the same. Maybe there's something else that I'm missing. – FLAW Nov 06 '22 at 13:59
  • it kinda comforts me: `class C_{static define(){return this}} const C = C_.define() let [c, c_] = [new C(), new C_()] console.log(c instanceof C, c instanceof C_, '\n', c_ instanceof C, c_ instanceof C_) ` – FLAW Nov 06 '22 at 14:07
  • @FLAW `B` and `C` are the same. Except one has a name, the other doesn't. Both are normal classes - if you add properties and/or methods to them, both would have them. – VLAZ Nov 06 '22 at 14:07
  • @VLAZ but `console.log(B === C) // false` – FLAW Nov 06 '22 at 14:11
  • @FLAW well *obviously they are not the same class*!!! They are, however, constructed exactly the same, and there would be no actual difference how you initialise them. Except the `name` property. I thought it was quite clear from the context that I do not consider them to be one and the same class. If *you* did, then you should have probably led with that. No, they aren't the same. `C` has that static method which `B` has which is a big giveaway they are not one thing. – VLAZ Nov 06 '22 at 14:16
  • oh gosh I felt so stupid. I dunno what I was thinking about when I wrote `===`. I understand you. so, there is nothing more than having `name` or not right? – FLAW Nov 06 '22 at 14:43