Question

Well I tried to figure out is this possible in any way. Here is code:

a=function(text)
{
   var b=text;
   if (!arguments.callee.prototype.get)
      arguments.callee.prototype.get=function()
    {
         return b;
    }
    else
      alert('already created!');
}

var c=new a("test");  // creates prototype instance of getter
var d=new a("ojoj");  // alerts already created
alert(c.get())        // alerts test 
alert(d.get())        // alerts test from context of creating prototype function :(

As you see I tried to create prototype getter. For what? Well if you write something like this:

a=function(text)
{
    var b=text;
    this.getText=function(){ return b}
}

... everything should be fine.. but in fact every time I create object - i create getText function that uses memory. I would like to have one prototypical function lying in memory that would do the same... Any ideas?

EDIT:

I tried solution given by Christoph, and it seems that its only known solution for now. It need to remember id information to retrieve value from context, but whole idea is nice for me :) Id is only one thing to remember, everything else can be stored once in memory. In fact you could store a lot of private members this way, and use anytime only one id. Actually this is satisfying me :) (unless someone got better idea).

someFunc = function()
{
  var store = new Array();
  var guid=0;
  var someFunc = function(text)
  {
    this.__guid=guid;
    store[guid++]=text;
  }

  someFunc.prototype.getValue=function()
  {
    return store[this.__guid];
  }

  return someFunc;
}()

a=new someFunc("test");
b=new someFunc("test2");

alert(a.getValue());
alert(b.getValue());
Was it helpful?

Solution

JavaScript traditionally did not provide a mechanism for property hiding ('private members').

As JavaScript is lexically scoped, you could always simulate this on a per-object level by using the constructor function as a closure over your 'private members' and defining your methods in the constructor, but this won't work for methods defined in the constructor's prototype property.

Of course, there are ways to work around this, but I wouldn't recommend it:

Foo = (function() {
    var store = {}, guid = 0;

    function Foo() {
        this.__guid = ++guid;
        store[guid] = { bar : 'baz' };
    }

    Foo.prototype.getBar = function() {
        var privates = store[this.__guid];
        return privates.bar;
    };

    Foo.prototype.destroy = function() {
        delete store[this.__guid];
    };

    return Foo;
})();

This will store the 'private' properties in another object seperate from your Foo instance. Make sure to call destroy() after you're done wih the object: otherwise, you've just created a memory leak.


edit 2015-12-01: ECMAScript6 makes improved variants that do not require manual object destruction possible, eg by using a WeakMap or preferably a Symbol, avoiding the need for an external store altogether:

var Foo = (function() {
    var bar = Symbol('bar');

    function Foo() {
        this[bar] = 'baz';
    }

    Foo.prototype.getBar = function() {
        return this[bar];
    };

    return Foo;
})();

OTHER TIPS

Methods on the prototype cannot access "private" members as they exist in javascript; you need some kind of privileged accessor. Since you are declaring get where it can lexically see b, it will always return what b was upon creation.

After being hugely inspired by Christoph's work-around, I came up with a slightly modified concept that provides a few enhancements. Again, this solution is interesting, but not necessarily recommended. These enhancements include:

  • No longer need to perform any setup in the constructor
  • Removed the need to store a public GUID on instances
  • Added some syntactic sugar

Essentially the trick here is to use the instance object itself as the key to accessing the associated private object. Normally this is not possible with plain objects since their keys must be strings. However, I was able to accomplish this using the fact that the expression ({} === {}) returns false. In other words the comparison operator can discern between unique object instances.

Long story short, we can use two arrays to maintain instances and their associated private objects:

Foo = (function() {
    var instances = [], privates = [];

    // private object accessor function
    function _(instance) {
        var index = instances.indexOf(instance), privateObj;

        if(index == -1) {
            // Lazily associate instance with a new private object
            instances.push(instance);
            privates.push(privateObj = {});
        }
        else {
            // A privateObject has already been created, so grab that
            privateObj = privates[index];
        }
        return privateObj;
    }

    function Foo() {
        _(this).bar = "This is a private bar!";
    }

    Foo.prototype.getBar = function() {
        return _(this).bar;
    };

    return Foo;
})();

You'll notice the _ function above. This is the accessor function to grab ahold of the private object. It works lazily, so if you call it with a new instance, it will create a new private object on the fly.

If you don't want to duplicate the _ code for every class, you can solve this by wrapping it inside a factory function:

function createPrivateStore() {
    var instances = [], privates = [];

    return function (instance) {
        // Same implementation as example above ...
    };
}

Now you can reduce it to just one line for each class:

var _ = createPrivateStore();

Again, you have to be very careful using this solution as it can create memory leaks if you do not implement and call a destroy function when necessary.

With modern browsers adopting some ES6 technologies, you can use WeakMap to get around the GUID problem. This works in IE11 and above:

// Scope private vars inside an IIFE
var Foo = (function() { 
    // Store all the Foos, and garbage-collect them automatically
    var fooMap = new WeakMap();

    var Foo = function(txt) { 
        var privateMethod = function() { 
            console.log(txt); 
        };
        // Store this Foo in the WeakMap
        fooMap.set(this, {privateMethod: privateMethod}); 
    } 

    Foo.prototype = Object.create(Object.prototype); 
    Foo.prototype.public = function() { 
        fooMap.get(this).p(); 
     } 
     return Foo; 
 }());

 var foo1 = new Foo("This is foo1's private method");
 var foo2 = new Foo("This is foo2's private method");
 foo1.public(); // "This is foo1's private method"
 foo2.public(); // "This is foo2's private method"

WeakMap won't store references to any Foo after it gets deleted or falls out of scope, and since it uses objects as keys, you don't need to attach GUIDs to your object.

Personally, I don't really like the solution with the guid, because it forces the developer to declare it in addition to the store and to increment it in the constructor. In large javascript application developers might forget to do so which is quite error prone.

I like Peter's answer pretty much because of the fact that you can access the private members using the context (this). But one thing that bothers me quite much is the fact that the access to private members is done in a o(n) complexity. Indeed finding the index of an object in array is a linear algorithm. Consider you want to use this pattern for an object that is instanciated 10000 times. Then you might iterate through 10000 instances each time you want to access a private member.

In order to access to private stores in a o(1) complexity, there is no other way than to use guids. But in order not to bother with the guid declaration and incrementation and in order to use the context to access the private store I modified Peters factory pattern as follow:

createPrivateStore = function () {
var privates = {}, guid = 0;

return function (instance) {
    if (instance.__ajxguid__ === undefined) {
        // Lazily associate instance with a new private object
        var private_obj = {};
        instance.__ajxguid__ = ++guid;
        privates[instance.__ajxguid__] = private_obj;
        return private_obj;
    }

    return privates[instance.__ajxguid__];
}

}

The trick here is to consider that the objects that do not have the ajxguid property are not yet handled. Indeed, one could manually set the property before accessing the store for the first time, but I think there is no magical solution.

I think real privacy is overrated. Virtual privacy is all that is needed. I think the use of _privateIdentifier is a step in the right direction but not far enough because you're still presented with a listing of all the _privateIdentifiers in intellisense popups. A further and better step is to create an object in the prototype and/or constructor function for segregating your virtually private fields and methods out of sight like so:

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method tucked away inside a nested privacy object called x
    x: {
      private: function () {
        console.log('PRIVATE method has been called');
      }
    },

  }

// Create an instance of the object
var mo = new MyObject(); 

now when the coder types "mo." intellisense will only show the public function and "x". So all the private members are not shown but hidden behind "x" making it more unlikely for a coder to accidentally call a private member because they'll have to go out of their way and type "mo.x." to see private members. This method also avoids the intellisense listing from being cluttered with multiple private member names, hiding them all behind the single item "x".

I know this thread is really really old now, but thought this solution might be of interest to anyone passing by:

const Immutable = function ( val ) {
    let _val = val;

    this.$ = {
        _resolve: function () {
            return _val;
        }
    };
};
Immutable.prototype = {
    resolve: function () {
        return this.$._resolve();
    }
};

Essentially hiding the internal _val from being manipulated and making an instance of this object immutable.

I have created a new library for enabling private methods on the prototype chain. https://github.com/TremayneChrist/ProtectJS

Example:

var MyObject = (function () {

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method, using (_)
    _private: function () {
      console.log('PRIVATE method has been called');
    }
  }

  return protect(MyObject);

})();

// Create an instance of the object
var mo = new MyObject();

// Call its methods
mo.public(); // Pass
mo._private(); // Fail
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top