Question:
How would you implement protected properties in ES6
classes in an elegant way? (that can be accessed only from inside the child class)
I am not searching a response like "ES don't have protected/package properties". It is already known. I want a nice and cleaner workaround to emulate protected properties.
I don't want to add security. Only a cleaner exposed interface to all the end users of the API
.
Example:
I have the following API
: (node)
let Symbols = {
_secret: Symbol("_secret")
};
class MyClass {
constructor() {
this.public = "This is public";
this[Symbols._secret] = "This is private";
}
}
// Set the Symbols to a static propietry so any class can access it and extend it
MyClass[Symbol.for("_Symbols")] = Symbols;
module.exports = MyClass
let MyClass = require("./my-class.js");
// extends protected properties with own properties
Symbols = Object.assign({}, MyClass[Symbol.for("_Symbols")] , {
_childSecret = Symbol("_childSecret")
});
class MyChildClass extends MyClass {
constructor() {
super();
this[Symbols._childSecret] = "This is also private";
console.log(this[Symbols._secret]); //logs "this is private"
console.log(this[Symbols._childSecret]); //logs "this is also private"
}
}
// Set the Symbols to a static propietry so any class can access it and extend it
MyClass[Symbol.for("_Symbols")] = Symbols;
module.exports = MyChildClass;
To use the class:
let MyChildClass = require("./my-child-class.js");
var c = new MyChildClass();
The advantages:
API
is cleaner. And the end user of the API
can view the exposed methods.The problem:
The code is "pretty" in the base class, but not that pretty in the child class. Is there any way to improve the order?
Anyone that can access to Symbol.for("_Symbols")
can access to all the protected/private properties of the API. (EDIT: I don't mind this. This is not a problem for me since if someone want to break the API accessing the internal symbols, it is they fault)
Your approach is pointless.
Symbols do not provide any security because they are public. You can get them so easily with Object.getOwnPropertySymbols
.
So if you don't care about security and just want simplicity, use a normal _secret
property.
class MyClass {
constructor() {
this.public = "This is public";
this._secret = "This is private";
}
}
module.exports = MyClass;
let MyClass = require("./my-class.js");
class MyChildClass extends MyClass {
constructor() {
super();
this._childSecret = "This is also private";
console.log(this._secret); // "this is private"
console.log(this._childSecret); // "this is also private"
}
}
module.exports = MyChildClass;