All classes, expressions or otherwise, create a new scope containing their name, if present, as an immutable binding. (This includes unnamed class expressions, though I think it is impossible for the scopes so created to contain any bindings.)
This means that class declarations always create two variables: the one you'd expect a declaration to create, by which other things can see it, and an inner one visible only to the class body (and the heritage expression, if present).
Example:
let s;
class C extends (s = () => C, null) {
f() { return C; }
}
let c = new C;
C = 0;
console.log(C /* 0 */, c.f() /* class */, s() /* class */);
All classes, expressions or otherwise, create a new scope containing their name, if present, as an immutable binding. (This includes unnamed class expressions, though I think it is impossible for the scopes so created to contain any bindings.)
This means that class declarations always create two variables: the one you'd expect a declaration to create, by which other things can see it, and an inner one visible only to the class body (and the heritage expression, if present).
Example: