In the book I am reading at the moment, it talks about how we can use WeakMap to enforce privacy with the example code below.
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;
})();
I can not understand how such code can truly make gear property private and won't allow access from outside.
it seems that by using
carProps.set(this, { userGear: this._userGears[0] });
we are hiding userGear and making it private so it can not be accessed.
However, when I use
const car1 = new Car("Toyota", "Prius");
console.log(car1);
console.log(car1.userGear);
it shows me the result of
Car {
make: 'Toyota',
model: 'Prius',
_userGears: [ 'P', 'N', 'R', 'D' ] }
P
I am not sure why I could access userGear and got 'P' instead of 'undefined' here where it is suppose to be not accessible.
Probably I am doing something wrong or understood the concept incorrectly.
Can someone please help me to understand the WeakMap?
The getter and setter of
userGearshown in the code is just there to show you how you could communicate between the (private)carPropsinside the class and the outer scope. The point of the example is to show that thecarPropsvariable cannot be accessed, except through the deliberately exposeduserGearmethods. If those methods didn't exist, then after setting the WeakMap in the constructor, the outside consumer ofCarwouldn't be able to see or do anything with it, eg:For another example that might make more sense, say that the constructor chose a random number that the user of the class had to guess:
With the above code, there's no way for the caller of
Gameto figure out Game's internal random number without calling (the deliberately exposed method).guessa few times. (unlessMath.randomgets monkeypatched beforehand...)