从 derived (ES2019 private class) 访问 base class 的受保护字段

Accessing protected fields of base class from derived (ES2019 private class)

我想从派生的 classes 访问基 class 的私有字段而不使它们成为 public(在其他语言中称为 'protected')。

考虑以下 class:

class Animal {

  #privateProp;

  constructor() {

  this.#privateProp = 12;

  }
}

现在扩展 class:

class Cat extends Animal {

  constructor() {

    super();
  }

  doIt() {

    console.log(this.#privateProp) // 1 below
    console.log(super.#privateProp) // 2 below
  }
}

我想像受保护一样执行:

new Cat().doIt();

但得到(分别):

  1. Uncaught SyntaxError: Private field '#privateProp' must be declared in an enclosing class
  2. Uncaught SyntaxError: Unexpected private field

请注意,当 privateProp 变为 public 时,此代码将完美运行,但我想实现类似受保护的行为,并像任何支持继承的语言一样访问 'private' 字段。

我们将不胜感激。

字段是私有的,类似于变量是块范围的;如果 属性 对某个 class 是私有的,则只能在 class 中引用它。如果您扩展 class,它将在派生的 class.

中不可见

你可以在 superclass 上创建一个 getter/setter,如果你想在 subclass 上用它做一些事情:

class Animal {
  #privateProp = 12;
  setProp(val) {
    this.#privateProp = val;
  }
  getProp() {
    return this.#privateProp;
  }
}
class Cat extends Animal {
  doIt() {
    console.log(this.getProp());
  }
}
new Cat().doIt();

另一种方法是将 "private" 字段定义为仅作用于 class 声明的 WeakMap:

const { Animal, Cat } = (() => {
  const privateProps = new WeakMap();
  class Animal {
    constructor() {
      privateProps.set(this, 12);
    }
  }
  class Cat extends Animal {
    doIt() {
      console.log(privateProps.get(this));
    }
  }
  return { Animal, Cat };
})();
new Cat().doIt();

you can create a private property with getter and setter methods having restricted access by checking if the constructor is not of the parent class itself.

class Animal {
  #privateProp = 12;
  set Prop(val) {
    if (this.constructor.name !== 'Animal')
      return this.#privateProp = val;
    throw new Error('Cannot Access Protected property');
  }
  get Prop() {
    if (this.constructor.name !== 'Animal')
      return this.#privateProp;
    throw new Error('Cannot Access Protected property');
  }
}

class Cat extends Animal {
  get Prop() {
    return super.Prop;
  }

  set Prop(val) {
    super.Prop = val
  }
}

let cat = new Cat();
console.log(cat.Prop)
cat.Prop = 22
console.log(cat.Prop)

console.log(new Animal().Prop);