JavaScript 中的私有 class 字段

Private class field in JavaScript

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

结果

同时

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

在 Firefox 和 Chrome

中均有效

AFAIK 实例字段将安装在 class 实例上,而静态字段将安装在 class 对象本身上。它们并不冲突。为什么之前的代码无效?

两次使用不同的变量名称,例如 ab 而不是 a

我猜这个变量不能严格地同时是静态的和非静态的。

仅供参考 - 此处支持私有 class 字段:https://caniuse.com/mdn-javascript_classes_private_class_fields

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

它们是,因为在表达式 x.#a 中引擎不知道 x 是 class 对象还是 class 实例。 #a token 的含义应该是静态的,不依赖于对象,它需要指代一个或另一个,但不能指代两者。

不同于由标识符的字符串值标识的普通字符串键控属性(.a.a 相同,无论上下文如何),私有字段具有标识(与符号不同) 是用他们的声明创建的。每个 class 定义只能存在一个 #a,在不同的 class 中,相同的 #a 语法将引用不同的字段。

在 class 中声明的带有 # 前缀的任何 属性 都被视为私有 属性。但是在 Javascript 中没有设计私有属性的概念。但是,我们可以通过在函数外部定义它们然后在函数内部使用它们来模拟私有属性。这样,除非我们导出,否则无法在模块外部访问这些属性。所以,上面代码的转译版本将是这样的。

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

如您所见,#a 变量被转换为 _a 并在函数外部声明为 WeakMap 并在函数内部使用。

因此,如果您有另一个具有相同名称 #a 的静态 属性,它会尝试在函数外部创建另一个具有相同名称 _a 的变量。因为它是 private static 属性 它不会附加到函数。所以转译后的代码将如下所示。

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
};

正如您所见,它尝试创建另一个具有相同名称的变量并抛出错误。这是 javascript 的限制,显然可以通过提供不同的名称轻松避免。

后一种情况有效,因为它们不是私有财产。