javascript - Technical differences in creating object with private member -


here found pattern of javascript module enabling private members of object. if got right, can written way:

var myobject1 = (function(){   var privatemember = 42;   return {     publicmember: function() {       return privatemember;     }   } })(); 

but there more effective way:

var myobject2 = new function() {   var privatemember = 42;   this.publicmember = function() {     return privatemember;   } } 

is there difference between two? there other possibilities implement private members?

this result chrome debugger:

enter image description here

there's couple of real technical differences between 2 (pointed out bergi in comments). differences aren't matter unless you're doing thousands , thousands of these. there's style difference, subjective, technical differences small. see breakdown below gory details.

at high level, both forms create new object, both rely on closure private member. second way uses bit more memory, because function can't garbage-collected after use, whereas in first one, can be. similarly, object created function's prototype property reclaimable in first version, not second. second way may less clear first (witness questions below @djechlin), not least because of implicit return value, that's style point.

re second question:

are there other possibilities implement private members?

for one-off objects yours, way you're doing best (either form, really). right now, there's sort of way, , of es.next (the next version of ecmascript), there's new private way. in both cases, though, it's more useful when you're doing classes of objects rather one-offs.

more in this entry on blog (which talks stuff coming es.next), i'll go salient details here.

the typical pattern private members in classes of objects looks this:

function foo(tobeprivate) {     var privatemember = tobeprivate;      this.method1 = function() {         // ...do private `privatemember`     }; } foo.prototype.method2 = function() {     // ...doesn't have access private `privatemember` };  var f = new foo("private stuff"); // f.method1() can use private data // f.method2() cannot 

the problem each , every object created via new foo gets own method1 function. don't reuse method2, there's one of them shared objects created new foo. (this isn't big deal modern engines, able reuse code of method1 though new method1 object created each foo object. there development patterns dynamically change prototype, unable act on method1 above.)

here's nearly-private pattern can today:

var foo = (function() {     // create private name object our private property     var privatekey = makerandomstring();      // our constructor         function foo(tobeprivate) {         this[privatekey] = tobeprivate;     }      // define private property it's non-enumerable     object.defineproperty(foo.prototype, privatekey, {         writable: true     });      // methods shared foo instances     foo.prototype.method1 = function() {         // ...use this[privatekey] here...     };     foo.prototype.method2 = function() {         // ...use this[privatekey] here...     };      return foo; })();  var f = new foo("private stuff"); // f.method1() can use private data // f.method2() can too! // both `method1` , `method2` *reused* `foo` objects 

...where makerandomstring that, gives new random string every time call it.

the property create not private, it's obscure. doesn't show in for-in loops (because property created non-enumerable) , name changes every time code runs. code attempting use private data must first figure out property name, non-trivial exercise code can't list of non-enumerable property names of object. naturally, though, 1 glance @ object in debugger shows property , value. property really obscure, not quite private.

this pattern improved markedly stuff coming in es.next, next version of ecmascript. we'll private name objects, useful on own , used the new classses.

here's how private names apply above:

// **es.next, not yet available in wild** import name "@name"; var foo = (function() {     // create private name object our private property     var privatekey = new name();      function foo(tobeprivate) {         this[privatekey] = tobeprivate;     }     foo.prototype.method1 = function() {         // ...use this[privatekey] here...     };     foo.prototype.method2 = function() {         // ...use this[privatekey] here...     };      return foo; })();  var f = new foo("private stuff"); // f.method1() can use private data // f.method2() can too! // both `method1` , `method2` *reused* `foo` objects 

properties created private name objects never show in for-in enumerations at all, , names not strings. code cannot access property name private name object without having that specific name object. since privatekey variable above private foo class, no other code can use property. it's private. naturally, these show in debuggers, then, nothing private debuggers.


@djechlin asked breakdown of how each of forms private member work, , helps understand difference between them bergi highlighted:

your first example:

var myobject1 = (function(){   var privatemember = 42;   return {     publicmember: function() {       return privatemember;     }   } })(); 

(this list leaves out few details don't think relevant.)

  1. a property called myobject1 created on current variable binding object (which may window if global) value undefined.

  2. the function expression evaluated:
    a) function object created.
    b) blank object created , assigned new function's prototype property.
    c) constructor property created on object , given reference function.
    d) reference current variable binding object stored on function.

  3. the function called, creating (amongst other things) variable binding object execution context of call.

  4. a property called privatemember created , assigned variable binding object step 3.

  5. the value 42 assigned privatemember property of vbo.

  6. a blank object created , given prototype object.prototype.

  7. the inner function expression evaluated, function object created (with blank object prototype property , constructor property put on object, , reference current variable binding object [the 1 step 3]).

  8. that function assigned property on blank object step 5 publicmember.

  9. a reference object step 6 returned main anonymous function.

  10. that object reference stored in myobject1 property created in step 1.

  11. the main anonymous function (from step 2) has no outstanding references, , can reclaimed gc; , object referenced prototype property can reclaimed gc.

your second example:

var myobject2 = new function() {   var privatemember = 42;   this.publicmember = function() {     return privatemember;   } } 

(again, irrelevant details left out.)

  1. a property called myobject2 created on current variable binding object (which may window if global) value undefined.

  2. the function expression evaluated:
    a) function object created.
    b) blank object created , assigned new function's prototype property.
    c) constructor property created on object , given reference function.
    d) reference current variable binding object stored on function.

  3. a new, blank object created , assigned prototype anonymous function's prototype property.

  4. the function called object step 3 passed in this, creating (amongst other things) variable binding object execution context of call.

  5. a property called privatemember created , assigned variable binding object step 4.

  6. the value 42 assigned privatemember property of vbo.

  7. the inner function expression evaluated, function object created (with blank object prototype property , constructor property put on object, , reference current variable binding object [the 1 step 4]).

  8. that function assigned property on blank object step 5 publicmember.

  9. the function returns, , because doesn't return object, result of new expression reference object created in step 3.

  10. that object reference stored in myobject2 property created in step 1.

  11. the main anonymous function (from step 2) cannot reclaimed gc, because myobject2's underlying prototype has reference on constructor property (and both function , object assigned prototype property remain in memory).

you release function (but not object assigned prototype property) adding line inside it:

delete this.constructor.prototype.constructor; 

that removes reference function object assigned prototype property. object remains myobject2's underlying prototype, no longer refers function, function eligible gc.

but @ point, we're obscurity land. :-)

conclusions

so they're same, small difference main anonymous function , object on prototype property aren't eligible gc. take thousands , thousands of these matter in real world.

(side note: implementations may defer of steps of creating function — such creating blank object prototype property , setting constructor — until/unless prototype property used, since of course in vast majority of cases, it's never used, because vast majority of functions never used constructor functions. first form may a little tiny teeny bit more efficient because can skip steps. it's difference unlikely matter unless you're doing thousands of these.)


fwiw, first can written this, if concern number of lines, number of parentheses, or not liking object literal, etc.:

var myobject1 = function(){   var obj = {};   var privatemember = 42;   obj.publicmember = function() {     return privatemember;   };   return obj; }(); 

as matter of style, prefer explicit return, that's matter of style.


Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -