Ciberman Ciberman - 23 days ago 5
Javascript Question

Protected properties in ES6 classes (using Symbols?)

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)

In
my-class.js
:

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


In
my-child-class.js
:

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:


  • The exposed
    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)


Answer

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;