4
class A {
  #a = 1;
  static #a = 2;
}

Results in

  • Uncaught SyntaxError: redeclaration of private name #a in Firefox
  • Uncaught SyntaxError: Identifier '#a' has already been declared in Chrome

While

class A {
  a = 1;
  static a = 2;
}

is valid in both Firefox and Chrome

AFAIK instance fields will be installed on the class instance while static fields will be installed on the class object itself. They are not conflicted. Why the former code is invalid?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Carter Li
  • 149
  • 12

3 Answers3

2

Instance fields will be installed on the class instance while static fields will be installed on the class object itself. They are not conflicted.

They are, because in the expression x.#a the engine doesn't know whether x is a class object or a class instance. The meaning of the #a token should be static and not depend on the object, it needs to refer to the one or to the other but not to both.

Unlike normal string-keyed properties that are identified by the string value of the identifier (.a is the same as .a regardless of context), private fields have an identity (not unlike symbols) that is created with their declaration. Only one #a can exist per class definition, and in a different class the same #a syntax will refer to a different field.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 'They are, because in the expression x.#a the engine doesn't know whether x is a class object or a class instance.' The engine doesn't know it when parsing but knows it on runtime. I don't think it's a problem. – Carter Li Jun 11 '21 at 01:54
  • @CarterLi It *could* do it at runtime, but that's not how class fields were designed to work - they're *supposed* to be distinguishable at compile time. – Bergi Jun 11 '21 at 01:57
  • How can they be fully identifiable at compile time? The engine doesn't even know x is an object or not. – Carter Li Jun 11 '21 at 02:03
  • Does the standard say anything about this? – Carter Li Jun 11 '21 at 02:03
  • 1
    @CarterLi The engine doesn't know what `x` is, but it knows exactly which field ("private name") it attempts to access in it. The standard is pretty clear about how `#a` needs to lexically resolve to one field ("private name"). – Bergi Jun 11 '21 at 02:16
  • I found it: https://tc39.es/proposal-class-fields/#sec-private-names. Thanks – Carter Li Jun 11 '21 at 02:28
1

Any property declared in a class with # prefix is treated as private property. But there is no private properties concept in Javascript by design. However, we can mimic private properties by defining them outside the function and then using them inside the function. This way those properties are not accessible outside the module unless we export. So, the transpiled version for the above code will be like this.

var _a = /*#__PURE__*/new WeakMap();
var A = function A() {
   _classCallCheck(this, A);
  _a.set(this, {
    writable: true,
    value: 1
  });
};

As you can see the #a variable is transformed as _a and declared outside the function as WeakMap and being used inside the function.

So if you have another static property with the same name #a it tries to create another variable outside the function with the same name _a. Since it is private static property it will not be attached to the function. So the transpiled code will look like this.

var _a = /*#__PURE__*/new WeakMap();
var A = function A() {
   _classCallCheck(this, A);
  _a.set(this, {
    writable: true,
    value: 1
  });
};

var _a = {
  writable: true,
  value: 2
};

So as you can see it tries to create another variable with the same name and throws the error. This is the limitation of the javascript and can be easily avoided by giving a different name obviously.

The later case is valid because they are not private properties.

Vikram Kumar
  • 300
  • 2
  • 10
  • A feature can be polyfilled like this doesn't mean that the JS engine will implement it like this. There are features can't be polyfilled at all ( like proxies ) – Carter Li Jun 11 '21 at 02:06
0

Use different variable names like a and b instead of a both times.

The variable cannot strictly be static and non-static at the same time I am guessing.

FYI - support for private class fields is here: https://caniuse.com/mdn-javascript_classes_private_class_fields

Peter Krebs
  • 3,831
  • 2
  • 15
  • 29