1

在我目前正在阅读的书中,它讨论了我们如何使用 Wea​​kMap 通过下面的示例代码来强制隐私。

const Car = (function() {
  const carProps = new WeakMap();
  class Car {
    constructor(make, model) {
      this.make = make;
      this.model = model;
      this._userGears = ["P", "N", "R", "D"];
      carProps.set(this, { userGear: this._userGears[0] });
    }
    get userGear() {
      return carProps.get(this).userGear;
    }
    set userGear(value) {
      if (this._userGears.indexOf(value) < 0)
        throw new Error(`Invalid gear: ${value}`);
      carProps.get(this).userGear = value;
    }
    shift(gear) {
      this.userGear = gear;
    }
  }
  return Car;
})();

我无法理解这样的代码如何真正使齿轮属性私有并且不允许从外部访问。

似乎通过使用

carProps.set(this, { userGear: this._userGears[0] });

我们正在隐藏 userGear 并将其设为私有,因此无法访问。

但是,当我使用

const car1 = new Car("Toyota", "Prius");
console.log(car1);
console.log(car1.userGear);

它向我展示了结果

Car {
  make: 'Toyota',
  model: 'Prius',
  _userGears: [ 'P', 'N', 'R', 'D' ] }
P

我不知道为什么我可以访问 userGear 并在此处获取 'P' 而不是 'undefined' 假设它无法访问。

可能我做错了什么或错误地理解了这个概念。

有人可以帮我理解 WeakMap 吗?

4

1 回答 1

2

代码中显示的 getter 和 setteruserGear只是为了向您展示如何carProps在类内部的(私有)和外部范围之间进行通信。该示例的重点是表明carProps无法访问该变量,除非通过故意公开的userGear方法。如果这些方法不存在,那么在构造函数中设置 WeakMap 后,外部使用者Car将无法看到或对其进行任何操作,例如:

const Car = (function() {
  const carProps = new WeakMap();
  class Car {
    constructor(make, model) {
      this.make = make;
      this.model = model;
      this._userGears = ["P", "N", "R", "D"];
      carProps.set(this, { userGear: this._userGears[0] });
    }
    shift(gear) {
      this.userGear = gear;
    }
  }
  return Car;
})();

const car = new Car('foo', 'bar');
// at this point, at this level of scope,
// there is no way for a user of "car" or "Car" to reference carProps
console.log(car.userGear);

对于另一个可能更有意义的示例,假设构造函数选择了类用户必须猜测的随机数:

const Game = (function() {
  const gameProps = new WeakMap();
  return class Game {
    constructor() {
      gameProps.set(this, { randomNum: Math.floor(Math.random() * 10) });
    }
    guess(num) {
      return gameProps.get(this).randomNum === num ? 'Win' : 'Lose';
    }
  }
})();

const game = new Game();
// at this point, at this level of scope,
// there is no way for a user of "Game" or "game" to reference gameProps
// or to figure out the random number, without guessing multiple times
console.log(
  game.guess(1),
  game.guess(2),
  game.guess(3),
  game.guess(4),
  game.guess(5)
);

使用上面的代码,调用者Game不调用(故意暴露的方法).guess几次就无法计算出Game的内部随机数。(除非Math.random事先得到猴子补丁......)

于 2019-10-13T11:53:19.077 回答