关于WeakMap和私有变量的问题
Questions about WeakMap and private variables
在我目前正在阅读的书中,它谈到了我们如何使用 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' 而不是 'undefined' 这里应该是无法访问的。
可能是我做错了什么或者理解错了这个概念。
有人可以帮助我理解 WeakMap 吗?
代码中显示的 userGear
的 getter 和 setter 只是为了向您展示如何在 class 和外部范围。该示例的要点是表明无法访问 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);
另一个可能更有意义的例子,假设构造函数选择了 class 的用户必须猜测的随机数:
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
事先得到 monkeypatched...)
在我目前正在阅读的书中,它谈到了我们如何使用 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' 而不是 'undefined' 这里应该是无法访问的。
可能是我做错了什么或者理解错了这个概念。
有人可以帮助我理解 WeakMap 吗?
代码中显示的 userGear
的 getter 和 setter 只是为了向您展示如何在 class 和外部范围。该示例的要点是表明无法访问 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);
另一个可能更有意义的例子,假设构造函数选择了 class 的用户必须猜测的随机数:
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
事先得到 monkeypatched...)