【问题标题】:How to simulate protected variables in javascript classes?如何在 javascript 类中模拟受保护的变量?
【发布时间】:2021-11-16 18:43:47
【问题描述】:

javascript 中模拟受保护变量的最佳方法是什么?

class Parent{

    #variable; // Private variable. This is not to be public.

    constructor(value)
    {
        this.#variable = value;
    }
}

class Child extends Parent{

    getNewVariable()
    {
        return (1 + this.#variable); // Uncaught SyntaxError: Private field '#variable' must be declared in an enclosing class
                                     // We want #variable to be accessible without making it public.
    }
}

由于 javascript 还不支持受保护的变量,

从扩展类中的超类访问私有变量的最佳选择是什么?

我找不到太多关于此的文档,所以任何建议都会非常有帮助。

【问题讨论】:

  • getter 和 setter 呢?
  • 嗨@ClausBönnhoff:感谢您的建议。 Getter 和 setter 确实有效,但我希望减少语法糖:为每个变量编写 get variable(){ return this.#variable; } 并不理想。但是,如果这是唯一的选择,那么它将不得不这样做。 :)
  • 使用打字稿。
  • 受保护的属性本质上是公共的,因为每个人都可以扩展类。因此,首先将其公开。不要尝试模拟不同的语言,而是编写惯用的 JavaScript。

标签: javascript class inheritance private protected


【解决方案1】:

+++ 迟到的答案,但我们开始... +++

基于WeakMap 的方法很可能涵盖了 OP 正在寻找的内容...

const protectedStatesMap = new WeakMap;

class Parent{
  constructor(foo) {
    protectedStatesMap.set(this, { foo });
  }
  getFoo() {
    return protectedStatesMap.get(this).foo;
  }
}
class Child extends Parent{
  constructor(foo, bar) {
    super(foo);

    Object.assign(protectedStatesMap.get(this), { bar })
  }
  getBar() {
    return protectedStatesMap.get(this).bar;
  }
}
const childA = new Child('foo', 'bar');
const childB = new Child('baz', 'biz');

console.log('childA.getFoo() ...', childA.getFoo());
console.log('childA.getBar() ...', childA.getBar());

console.log('childB.getFoo() ...', childB.getFoo());
console.log('childB.getBar() ...', childB.getBar());
.as-console-wrapper { min-height: 100%!important; top: 0; }

【讨论】:

  • @AndrewKhassapov ...查看这个迟到的答案的上述解决方案。
  • 谢谢@PeterSeliger!
【解决方案2】:

使用 TypeScript 怎么样? TypeScript 类支持 protected 关键字 (see docs),并且比原生 JavaScript 有很多额外的好处。

【讨论】: