📜 ⬆️ ⬇️

Honest private properties in the prototype

Hello!

Over the past 10 years (Happy birthday, prototype.js!) A lot of libraries have been written to emulate a full-fledged OOP in javascript.
All of them, one way or another, solved the problem of implementing private members of a class.

There are many broken spears and as a result, the developers were divided into 2 parts:
The first hides private properties in the scope of the constructor and refuses to use prototypes (creates methods for each instance of the object again), the second simply uses a convention in names like "_privateProperty" and in fact does not encapsulate the data.
')


Theory:

The new keyword allows you to call a function in such a way that inside it this will be equal to an empty object with the methods of the prototype. Thus, inside the constructor, you can form an object that will return from the constructor without explicitly specifying return.

var Animal = function(name){ this._privateName = name; }; Animal.prototype.getName = function(){ return this._privateName; }; var a = new Animal('Cow'); a._privateName === a.getName(); /* true */ 


But if the function called with new explicitly returns any value other than primitive types (strings, numbers, NaN, etc.), then this is the exact result that will return, despite the fact that the same empty object and methods will be accessible through this constructor from the prototype.

Practice:

If we accept that all this properties are private, and we explicitly return public ones, then we get an elegant emulation of private properties:

 var Animal = function(name){ var self = this; this._privateName = name; return { hello: Animal.prototype.hello.bind(this) }; }; Animal.prototype.getName = function(){ return this._privateName; }; Animal.prototype.hello = function(){ return 'hello ' + this.getName(); }; var a = new Animal('Cow'); a._privateName; /* undefined */ a.getName(); /* Exception */ a.hello(); /* hello Cow */ 


For example, I wrote a simple function that "wraps" the constructor and hides the private methods from the prototype:
github.com/poluyanov/privatize/blob/master/privatize.js

Pros:
  1. The main advantage of this approach is that, on a large number of objects, working with prototypes and their methods is initially faster than the traditional creation of methods for each object instance: jsperf.com/scopevsprototype
  2. Sometimes it can be convenient to dynamically override prototype methods for a number of objects.
  3. Inside the prototype, you can hide (really!) Common fields for a variety of objects (for example, counters).


Minuses:
  1. Since the constructor function returns a simple object, instanceof does not work;
  2. Such an approach may seem implicit and unobvious to some.


The method does not claim to be innovative, and perhaps you often use this approach in your work. I will be glad to your comments.

Source: https://habr.com/ru/post/251477/


All Articles