A class declared inside closure instead of a standard class without closure

I usually use the standard prototype-based OOP approach, and my class looks like

var std = function(){ this.log = function(msg){ console.log("want to be private. " + msg) }; }; std.prototype = { logInfo: function(msg){ this.log(msg); } }; 

but in this case log is a public method and anyone can use it. But I want to make it private, but still available in the methods declared in the prototype. For this we need a closure. The code will change to this

 var closureStd = (function(){ var std = function(){}; var log = function(msg){ console.log("I'm really private, youhooo!" + msg) }; std.prototype = { logInfo: function(msg){ log(msg); } }; return std; })(); 

So my question is: what is the difference between std and closureStd and what is the price I need to pay in order to be able to call private methods from the prototype?

+6
source share
3 answers

What is the difference between std and closStd?

The std constructor creates a new method for each call, but closureStd does not. You should have done it

 function std(){} std.prototype = { log: function(msg){ console.log("want to be private. " + msg) }, logInfo: function(msg){ this.log(msg); } }; 

And, of course (you already know), the log function in closureStd is stored in a (private) variable, and in the std instance it is accessible (and overwritten) externally on each instance (or on their prototype). In closure, this is a variable search in the scope chain (which can be considered static), while for a method, it is a search for properties on an object (and its prototype chain), which can be dynamic, but equally optimized in modern machines.

What is the price I need to pay to be able to call private methods from the prototype?

Is absent. The module template is simple and cheap, variable searches in a static chain are very fast. I would rather worry about memory since you are creating so many method instances in the constructor.

+2
source

I also did some tests to measure performance (the result will be in the console), and I believe that putting the class in closure demonstrates better performance, comparable to putting methods in the constructor. You also have inheritance options. Therefore, at the moment I do not see any flaws and will always use the class inside closure when I need private methods.

+1
source

Note that the module template provided by the link does not contain the properties of a private instance. It works great for function properties, since the function will not change for each instance, but is a little unlikely for value properties, as the following code shows:

 var module = (function () { // private variables and functions var foo = 'bar'; // constructor var module = function (name) { // instance variables this.name=name; }; // prototype module.prototype = { constructor: module, something: function () { // notice we're not using this.foo console.log("foo in "+this.name+" is:",foo); foo="new value"; } }; // return module return module; })(); var m1 = new module("m1"); var m2 = new module("m2"); m1.something();// foo in m1 is: bar m1.something();// foo in m1 is: new value m2.something();// foo in m2 is: new value 

As you can see in the last line of code, an instance of m1 and m2 has a private variable foo (all instances will point to the same value).

What I could do from another link that Bondye posted was that it was difficult to model privacy in JavaScript, and you might consider using a naming convention to indicate properties is private. You can use something like a google compiler and comment on JS code to indicate privates; but using a compiler with closure has its drawbacks (the libraries used cannot be compiled if the Closure Compiler is not compatible, and the code must be in a specific format, which must be compiled in advanced mode).

Another option is to completely throw out the prototype (at least for everything, using private properties) and put everything in the body of the constructor function (or use the function that returns the object).

 // function returning an object function makeObj(name){ // private vars: var foo = "bar"; return { name:name, something:function(){ console.log("foo in "+this.name+" is:",foo); foo="new value"; } } } var m1=makeObj("m1"); var m2=makeObj("m2"); m1.something();// foo in m1 is: bar m1.something();// foo in m1 is: new value m2.something();// foo in m2 is: bar // constructor with everything in the constructor body: function Obj(name){ // private vars: var foo = "bar"; this.name=name; this.something=function(){ console.log("foo in "+this.name+" is:",foo); foo="new value"; } } Obj.prototype.someOtherFunction=function(){ // anything here can't access the "private" variables } var m1=new Obj("m1"); var m2=new Obj("m2"); m1.something();// foo in m1 is: bar m1.something();// foo in m1 is: new value m2.something();// foo in m2 is: bar 

Another problem that you may encounter when using private instance values ​​is that they are only available in the instance. When you want to clone an object and define the clone function in your object to create a new instance, you need to write public access functions to set private values, because you cannot set them directly, as in Java Private Fields .

Additional information on using constructor functions here: Prototypic inheritance - record

+1
source

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


All Articles