JavaScript - prototype private variable access

[Yes, I read several answers to similar questions, but didn’t really get the answer I'm looking for, so I'm going to ask my question anyway.]

In the code below, how can I put the setSecret and tellSecret methods into a secret prototype while maintaining access to the private instance variable _secret and also returning the same result?

I tried this (see jsbin ) which placed the methods in the prototype but changed the output.

function Secret() {

    // ===== private =====

    var _secret;

    // ===== public =====

    this.setSecret = function (secret) {
        _secret = secret;
    };

    this.tellSecret = function () {
        console.log(_secret);
    };
}

var secretA = new Secret();
var secretB = new Secret();

secretA.setSecret("AAA");
secretB.setSecret("BBB");

setTimeout(function () {
    console.log("Secret A");
    secretA.tellSecret();

    console.log("Secret B");
    secretB.tellSecret();
}, 1000);


// ===== output =====

Secret A
AAA
Secret B
BBB
+4
source share
4 answers

, . , .
. ( : fooobar.com/questions/6183/...)

JavaScript , , .
, this - , .
"private" this, , . , , , - _private.

, , this. , , .

_private

, , _private , . , , , , , .
_private, .
, JS , .

+6

, , WeakMap, . , . WeakMaps FireFox Chrome Node.JS, , .

. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap .

var Secret = (function(){

   var secrets=new WeakMap();

  function Secret() {

    // ===== private =====

    secrets.set(this, null);

   // ===== public =====

   }

    Secret.prototype.setSecret = function (secret) {
       secrets.set(this, secret);
    };

    Secret.prototype.tellSecret = function () {
        console.log(secrets.get(this));
    };


   return Secret;

}());


var secretA = new Secret();
var secretB = new Secret();

secretA.setSecret("AAA");
secretB.setSecret("BBB");

setTimeout(function () {
    console.log("Secret A", secretA  );
    secretA.tellSecret();

    console.log("Secret B", secretB );
    secretB.tellSecret();
}, 1000);
+1

, , , , . .

var Secret = (function () {
    var instance = 0,
        p = [];

    function Secret() {
        this.i = instance++;
        p[this.i] = {};
        p[this.i]._secret = null;
    }

    Secret.prototype.setSecret = function (secret) {
        p[this.i]._secret = secret;
    };

    Secret.prototype.tellSecret = function () {
        console.log(p[this.i]._secret);
    };

    return Secret;
})();

var secret = new Secret();
secret.setSecret("A");

var secret2 = new Secret();
secret2.setSecret("B");

console.log(secret._secret)  // => undefined

secret.tellSecret()          // => A
secret2.tellSecret()         // => B
0

Try this one and tell me if this is what you are looking for.
To make the fragment more interesting, I added 2 more private properties to my secret. (Please note that all your personal vars are really closed)

function Secret() {
  // ===== private =====	
  var _properties = { secret:null, secret2:null, secret3:null } // <-- Put all yours properties here

  // ===== public =====
  this.getset = function(PROP, V) { 
        if(typeof V !== "undefined") _properties[PROP]=V; return _properties[PROP]; 
  }
}

 // Create GETTER & SETTER for each of yours properties
 MAKE_GET_SET(Secret, "secret", true, true);    // get and set 
 MAKE_GET_SET(Secret, "secret2", true, true);   // only set
 MAKE_GET_SET(Secret, "secret3", true, false);  // only get


/* === "Magic function" ;-) to create new properties GETTER & SETTER ============= */
function MAKE_GET_SET(OBJ, PROPNAME, makeGET /* boolean */, makeSET /* boolean */) {  
      Object.defineProperty( OBJ.prototype, PROPNAME, { 
        get: function() { return makeGET ? this.getset(PROPNAME) : null; }, 
        set: function(V) { if(makeSET) this.getset(PROPNAME,V); }, 
        enumerable: true
      } );
} 
/* ================================================================================= */

var secretA = new Secret();
var secretB = new Secret();

secretA.secret = "AAA";  // <-- here use setter
secretB.secret = "BBB";  // <-- here use setter

setTimeout(function () {
    console.log("Secret A: "+secretA.secret);  // <-- here use getter
    console.log("Secret B: "+secretB.secret);  // <-- here use getter
}, 1000);

/* ===== output =====

Secret A: AAA
Secret B: BBB

 ===== output ===== */
Run codeHide result
0
source

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


All Articles