What options do I have to achieve privacy on values I need to save in this
in a constructor function? For example, a simple Stack
implementation:
function Stack(){
this._stack = {}
this._counter = 0
}
Stack.prototype.push = function (item){
this._stack[this._counter++] = item
return this
}
Stack.prototype.pop = function (){
Reflect.deleteProperty(this._stack, --this._counter);
return this
}
Stack.prototype.peek = function (){
return this._stack[this._counter - 1]
}
Stack.prototype.length = function (){
return Object.values(this._stack).length
}
If these methods are not defined as prototype methods, I can easily private them like this:
function Stack(){
let _stack = {}
let _counter = 0
this.push = function (item){
_stack[_counter++] = item
return this
}
this.pop = function (){
Reflect.deleteProperty(_stack, --_counter);
return this
}
this.peek = function (){
return _stack[_counter - 1]
}
this.length = function (){
return Object.values(_stack).length
}
}
This way _stack
and _counter
are not exposed, but then these methods are not on prototype chain.
Is it possible to achieve privacy, while the protected values are saved in this
?
Alternatively, we may also use the “this” keyword to make method (function) calls to stick to the main method itself which thus makes the variables private. The main idea for using the “this” keyword is just to make things directly visible that is making methods directly accessible.
Short answer, no, there is no native support for private properties with ES6 classes. But you could mimic that behaviour by not attaching the new properties to the object, but keeping them inside a class constructor, and use getters and setters to reach the hidden properties.
A constructor enables you to provide any custom initialization that must be done before any other methods can be called on an instantiated object. The ValidationError class doesn't need an explicit constructor, because it doesn't need to do any custom initialization.
In its current state, there is no “direct” way to create a private variable in JavaScript.
This answer does not create private properties. However if the intent of the question is to prevent a user from accidentally accessing "private" properties or to prevent property conflict you can use symbols.
A property conflict happens when your function expects property A, while a library (or any other code) also expects property A but for another purpose.
const Stack = (function () {
const stack = Symbol("_stack");
const counter = Symbol("_counter");
function Stack() {
this[stack] = {};
this[counter] = 0;
}
Stack.prototype.push = function (item) {
this[stack][this[counter]++] = item;
return this;
};
Stack.prototype.pop = function () {
Reflect.deleteProperty(this[stack], --this[counter]);
return this;
};
Stack.prototype.peek = function () {
return this[stack][this[counter] - 1];
};
Stack.prototype.length = function () {
return Object.values(this[stack]).length;
};
return Stack;
})();
The above code does not prevent a user from accessing the properties, but makes it somewhat hard. You could still access them using the following code:
const stack = new Stack();
const [_stack, _counter] = Object.getOwnPropertySymbols(stack);
stack[_stack] // gives access to the stack
stack[_counter] // gives access to the counter
Symbol properties are excluded from a lot of common functions like Object.keys()
, Object.values()
, Object.entries()
, and also from for...in
loops.
Here is an example of using private fields. You can make them static with the static
keyword, but that is not necessary in this example.
class test {
#lol = 29;
#mas = 15;
constructor() {
this.#lol++;
this.#mas--;
return {
value: this.#lol - this.#mas
};
}
};
console.log(new test().value); // --> 16
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With