简体   繁体   中英

Access private members in prototype functions

When adding a new function to a prototype like this you don't have access to variables defined in the constructor function because they are out of scope.

function Thing() {
    var something = 357;
}

Thing.prototype.doSomething = function () {
    // no access to something because it is out of scope
    console.log(something);
};

Thanks to closures when adding the function to the prototype within the constructor function it has access to variables defined there.

function Thing() {
    var something = 357;

    Thing.prototype.doSomething = function () {
        console.log(something);
    };
}

Is this an okay way to get access to those variables or is there any better pattern to achieve the same goal? Are there any pitfalls I have to look out for?

You won't be able to access a private variable from the prototype. You can, however, access public variables. I have found that this is a good tradeoff:

function Thing() {
    this._something = 357;
}

Thing.prototype.doSomething = function () {
    console.log(this._something);
};

The naming convention of placing a _ before a property is just an informal way of marking it as private, even though it actually isn't.

There's some fatal flaws with your design:

  • The prototype function is redefined each time the constructor is called.
  • All instances will share the same variable.

Redefining functions each time the constructor is called is unavoidable with privileged functions, but if you choose to go down that path, you would define the functions directly on this rather than the prototype.

function SomeObject() {
    var privateVar = 'private value';

    this.somePriviledgedFunction = function () {
        //Use privateVar here
    };
} 

Now, with the support of WeakMap , there's a new pattern that would let you access private members from functions defined on the prototype. You would basically use an IIFE around your class declaration and have a shared WeakMap only visible within that scope to hold all private members. Object instances will be used as keys so that their values gets garbage collected when the objects are no longer around.

var SomeObject = (function (privates) {

    function SomeObject(someValue) {
        privates.set(this, {}); //initialze the privates scope
        privates.get(this).privateVar = someValue;
    }

   Object.defineProperty(SomeObject.prototype, 'privateVar', {
       get: function () {
           return privates.get(this).privateVar;
       }
   });

  return SomeObject;

})(new WeakMap());

var o1 = new SomeObject('first object');
var o2 = new SomeObject('second object');

o1.privateVar; //first object
o2.privateVar; //second object

However, note that every SomeObject 's prototype functions that need access to private variables will have to be defined within the same module (within the surrounding IIFE). Another issue would be that other instances of a class could potentially steal other's privates if one is not careful with the design, but not from any function defined outside the IIFE, so that's no a real issue to me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM