JavaScript的私有字段是按类还是按实例私有的?

4
JavaScript最近添加了私有类字段,以哈希前缀命名。

(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields)

我希望您能明确回答这种隐私形式是“按类”还是“按实例”的问题。
假设已定义了一个名为“Person”的类,并具有一个名为“#secret”的私有字段。
我使用“new”构造了两个Person类的实例:person1和person2。 person1是否可以访问并修改person2的#secret字段?
class Person {
  #secret;
  constructor(secret) {
    this.#secret = secret;
  }
  getSomebodyElsesSecret(somebody) {
    return somebody.#secret;
  }
  setSomebodyElsesSecret(somebody, value) {
    somebody.#secret = value;
  }
}

在你提供的 MDN 页面中已经有了答案:对于类字段,声明包括关键字 static。如果没有这个关键字,它们就是实例字段。你可以通过一个简单的测试程序轻松地证明这一点。 - Pointy
1
@pointy它们是实例字段。这并不意味着隐私是针对每个实例执行的。 - michaeljsalo
以井号前缀命名 - 不,不,不,请不要这样。 # 字符 正确的称呼是 _井号_(或 数字符号_,甚至对于一些奇怪的美国人来说是“磅”),但它绝对不会被称为“hashtag”。术语“hashtag”源于重新定义井号 "#" 以表示社交分类标签。你现在做的就像把轮椅称作无障碍厕所,或者指着在Staples出售的实际3.5英寸软盘并宣称它们是_save-icons... - Dai
1
从您引用的维基百科文章中,“符号本身有时被称为井号”。 - ATOMP
@ATOMP 是的,但我的立场来自于“规定主义者”学派。维基百科在提到其他人使用术语“hashtag”来指代该符号时是客观和正确的,但维基百科页面本身并没有权威地说#被正式或以其他方式命名为“hashtag”。我认为那些使用新词的人更可能是对符号历史的无知,而不是故意在写作中使用描述主义。 - Dai
1个回答

3

这些是按类别计算的 - 一个实例可以查看和修改另一个实例。

class Person {
  #secret;
  constructor(secret) {
    this.#secret = secret;
  }
  getSomebodyElsesSecret(somebody) {
    return somebody.#secret;
  }
  setSomebodyElsesSecret(somebody, value) {
    somebody.#secret = value;
  }
}

const a = new Person('a');
const b = new Person('b');
console.log(a.getSomebodyElsesSecret(b))
a.setSomebodyElsesSecret(b, 'c');
console.log(a.getSomebodyElsesSecret(b))

从一个角度来看,私有字段类似于仅限于类范围的变量 - 任何在类的{ }内部的东西都可以引用它们,但是在外部无法引用。

就作用域而言,它有点像定义私有变量的WeakMap和返回类的IIFE:

const Person = (() => {
    const secrets = new WeakMap();
    return class Person {
        constructor(secret) {
            secrets.set(this, secret);
        }
        getSomebodyElsesSecret(somebody) {
            return secrets.get(somebody);
        }
        setSomebodyElsesSecret(somebody, value) {
            secrets.set(somebody, value);
        }
    }
})();

const a = new Person('a');
const b = new Person('b');
console.log(a.getSomebodyElsesSecret(b))
a.setSomebodyElsesSecret(b, 'c');
console.log(a.getSomebodyElsesSecret(b))


JavaScript/ECMAScript有没有任何逃生口,允许访问那些私有属性?我记得在引入私有属性之前,有很多人询问是否有绕过保护的方法(类似于Java和.NET中的反射),因为不可避免地会有人需要这样做,例如解决外部依赖项中的错误等,但我不知道对话最终如何结束。 - Dai
我非常确定这是不可能的。另外,上面的WeakMap方法是它们被Babel转译的方式(或者至少非常相似),而且没有(好的)方法可以访问闭包内部。所有引用必须严格在定义它的“class”内部 - 即使是子类或超类也不能引用其他私有字段。 - CertainPerformance
@Dai 既然 JS 只是文本,你总是可以进行猴子补丁。甚至可以使用服务工作者来进行补丁。虽然不太美观,但如果第三方库中的错误导致了重大问题,这肯定是一个选项。 - Keith
@CertainPerformance 我记得我曾经不得不将一个eval应用程序传递到高阶函数中,以便玩弄其闭包,否则它是完全无法访问的,那真是有趣... - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接