I have an experience with the C# programming language, but I also have to work with the JS now and it's rather new for me.
I have tried to develop a simple class emulation in JS, like this:
function A( inputValue ) {
this.Init( inputValue );
this.Print();
}
A.prototype = {
value: null,
Init: function( inputValue ) {
this.value = inputValue;
},
Print: function () {
console.log( this.value );
}
}
var obj = new A(40);
I've tried to encapsulate the variable value
in A.prototype
, but it seems to be by JavaScript specification that all objects are available.
So my questions are:
1). How can I make an encapsulation , which is very close to the static languages with OOP/access modifiers support?
2). How can I emulate some access modifiers in JS, like private
for e.g.?
If you want to use inheritance, you cannot (at least AFAIK). For objects with no inheritance chain you can however use closures to get exactly the same effect. The question is if you actually really need properties to actually be completely private.
The closures approach
You can execute a function of which closure contains the variables you want to be private. These private variables do not actually belong to the object, but are only accesible by the methods of the object. For instance:
You can check it out here:
http://jsfiddle.net/MLF7v/1/
If you feel more comfortable with the Constructor function notation, you can do something like this:
(Not tested)
Which is pretty much the same as above, since the prototype is not used and the methods are copied directly into the object.
However, the closure approach are is memory and time consuming, and the worst: they make use of variables that do not in fact belong to the object you are working with... This is an important "semantic" problem (does this prop belong to me, or not?) that makes inheritance a headache. The reason for this, is that the methods of the extended objects either dont have access to that private pseudo-property (because they are not defined in the superobject closure), or have access to a common private variable from the "superobject" (the method was defined in the superobject and therefore access the closure of the superobject). That is a nonsense.
The "cultural" approach
In my humble opinion, encapsulation does not prevent anybody from messing with your code if he/she really wants to, so I prefer to follow the python philosophy "we are all mature people" which consists of using a convention to say "I would like this property not to be used from the outside". For instance, I prefix the private properties with '_', meaning that they're private, protected, or whatever but just stay away from it. And you don't touch what you should not touch.
This approach, appart from being the simplest and the most efficient, allows you for working with inheritance chains, since the properties are in the object and not confined in the closure.
Javascript still does not support encapsulation out of the box. However there is a proposal to make it so.
ECMA TC39 had proposed a private syntax. According to the proposal, in order to make a javascript class field private you need to prefix it with a hash '#'. This is to provide some sort of runtime encapsulation.
Example:
Chrome supports this since Chrome v74. If this private-syntax becomes a standart we will be able to benefit from runtime encapsulation in javascript.
You can use closures to encapsulate variables.
You can also imitate property getters and setters in generic way.
PS: Please don't set prototype directly, it breaks the prototype chain.
Encapsulation does not mean the computer is rigorously enforcing that you don't access something. It can be achieved simply by modules and classes not accessing each other's internals. If your program has that property then you are using encapsulation. Or at the very least you are gaining every benefit that encapsulation is said to give - potato, potahto.
If you need help with that you can use documentation and conventions like underscore prefixing so you know more easily what is internal or not.
Think about it - if you did global replace of "private" to "public" and recompiled any of your C# programs, it would function exactly the same. And you are somehow ignoring that even in C# one can access private through
.SetAccessible
if they so want. Since you seem to be ok with that, what is the problem?The emulation of "privates" through closures gives you far more and worse problems than it solves which I will list if you are not already convinced by the above.
I will also quote Martin Fowler for some argument of authority:
http://martinfowler.com/bliki/AccessModifier.html#AccessControlDoesNotControlAccess