为了账号安全,请及时绑定邮箱和手机立即绑定

关于 WeakMap 和私有变量的问题

关于 WeakMap 和私有变量的问题

守着星空守着你 2021-11-18 20:19:59
在我目前正在阅读的书中,它通过下面的示例代码讨论了我们如何使用 WeakMap 来强制执行隐私。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”而不是“未定义”。可能我做错了什么或错误地理解了这个概念。有人可以帮我理解 WeakMap 吗?
查看完整描述

1 回答

?
慕斯709654

TA贡献1840条经验 获得超5个赞

userGear代码中显示的 getter 和 setter只是为了向您展示如何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几次的情况下找出游戏的内部随机数。(除非Math.random事先得到猴子补丁......)


查看完整回答
反对 回复 2021-11-18
  • 1 回答
  • 0 关注
  • 184 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信