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

结果是

  • Uncaught SyntaxError: redeclaration of private name #a在火狐中
  • Uncaught SyntaxError: Identifier '#a' has already been declared在铬

尽管

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

在 Firefox 和 Chrome 中都有效

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

4

3 回答 3

2

实例字段将安装在类实例上,而静态字段将安装在类对象本身上。他们并不冲突。

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

与由标识符的字符串值标识的普通字符串键属性不同(.a.a上下文无关),私有字段具有使用其声明创建的标识(与符号不同)。#a每个定义只能存在一个class,并且在不同的类中,相同的#a语法将引用不同的字段。

于 2021-06-10T12:24:34.523 回答
1

在带有 # 前缀的类中声明的任何属性都被视为私有属性。但是 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。由于它是私有静态属性,因此不会附加到函数。所以转译后的代码将如下所示。

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 的限制,可以通过明显地给出不同的名称来轻松避免。

后一种情况是有效的,因为它们不是私有属性。

于 2021-06-10T12:44:40.493 回答
0

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

我猜该变量不能同时是静态和非静态的。

仅供参考 - 对私有类字段的支持在这里:https ://caniuse.com/mdn-javascript_classes_private_class_fields

于 2021-06-10T12:21:39.437 回答