11

Considering object creation patterns with private properties, one way to do is :

function MyStack (){
    var list = [],
        index = 0;

    this.push =  function(val){ 
        return list[index++] = val;
    };
    this.pop = function(){// ...}
}

var stack1 = new MyStack();       stack1.push(5);
var stack2 = new MyStack();       stack2.push(11);

Problem with this: Every instance of Stack has it's own copy of methods 'push' and 'pop'.

Another way for implementing constructor method is:

function MyStack(){ 
    this.list = []; 
    this.index = 0;
}
MyStack.prototype = {
    insert: function(val){
            return this.list[this.index++] = val;
        },
    pop:function(){//...}
}

Problem here: We lose the privacy of list and index.

Is there a way, such that we can have both methods reuse among instances and privacy of properties ?

I understand that we can have this for methods that don't operate on any state of the object, but I am talking more about those methods that do operate on the state.

9
  • You could give each instance a random ID and store its private properties in some kind of data structure. But I would suggest to just forget about privat properties if you use constructor functions. JavaScript is not built for that and any workaround has some disadvantage. Commented Sep 28, 2012 at 18:51
  • @FelixKling so lets say we have an auxiliary DS, Like {id1: { list:[3,4],currentIndex:2}, id2: { list:[2,1,4], currentIndex:3} } ... even then in the MyStack.prototype.insert = function(val){ currState = this.auxiliaryDS[this.id]; this.currState.list.push(val).. Again, it is not really private. Commented Sep 28, 2012 at 18:57
  • 1
    You could define the data store and the constructor function inside a function and only expose the constructor function. The data store would then be private and not be accessible from the outside. Yes, the ID would be accessible, but you could even generate a random property name for this if you wanted to obfuscate it. As I said, JS is not built for this and anything you do will be hacky and/or complex. Proper documentation is more valuable IMO. You can find quite a few related questions here: stackoverflow.com/… Commented Sep 28, 2012 at 19:06
  • @FelixKling Thanks. I see your point, Though I'd have to say it is a big statement when you say "JS is not built for this", considering the amount of flexibility with JS. ! Commented Sep 28, 2012 at 19:10
  • 1
    There isn`t really much of an answer here. But without getting abjectly ridiculous, you can wrap publicly-accessible methods in prototypes... or alternatively, you could keep a singular set of helper functions wrapped inside of a second, outer-closure, which wraps your intended constructor ("static", private functions). From there you can expose a command-type interface, which handles running the internal functionality, as well as registering individual instances, if needed, using private keys/indices. You'd never use Prototype, but you'd save memory by sharing helpers, but spend more clocks. Commented Oct 1, 2012 at 22:40

4 Answers 4

1

Yes. I've edited this code so it's actually fully functional as you had intended it to work. It seems a bit redundant to me, but, it does provide you the ability to provide a public interface, but to keep your variables private and control the way the user interacts with them.

function MyStack(){ 
    var list = []; 
    var index = 0;

    this.getIndex = function(){
        return index;
    }
    this.setIndex = function(val){
        index = val;
    }
    this.list = function(val){
        if(val){
           // setter if a value was provided. Illustrating how you can control
           // index, which I assume is the point of having these things private 
           // to begin with
           return list[this.setIndex(this.getIndex() + 1)] = val;
        }

        // always return list - acts like a getter
        return list;
    }
}
MyStack.prototype = {
    insert: function(val){
            return this.list(val);
        },
    pop:function(){}
}

var stack1 = new MyStack();       
stack1.insert(5);
var stack2 = new MyStack();       
stack2.insert(11);
Sign up to request clarification or add additional context in comments.

Comments

1

You should check out John Resig's Simple Javascript Inheritance. It is a great read, and it has been extended to provide support for privates, aptly called Privates.js;

1 Comment

Didn't know about the Privates.js.
1

A constructor function may return any object (not necesserily this). One could create a constructor function, that returns a proxy object, that contains proxy methods to the "real" methods of the "real" instance object. This may sound complicated, but it is not; here is a code snippet:

var MyClass = function() {
    var instanceObj = this;
    var proxyObj = {
        myPublicMethod: function() {
            return instanceObj.myPublicMethod.apply(instanceObj, arguments);
        }
    }
    return proxyObj;
};
MyClass.prototype = {
    _myPrivateMethod: function() {
        ...
    },
    myPublicMethod: function() {
        ...
    }
};

The nice thing is that the proxy creation can be automated, if we define a convention for naming the protected methods. I created a little library that does exactly this: http://idya.github.com/oolib/

2 Comments

This looks incredibly odd to me - could you explain it a little more? I read through your lib docs as well trying to grok it, but I'm not seeing exactly what the proxyObj object is doing
You can instantiate MyClass with myObj = new MyClass();. myObj will be the proxyObj: it will have only 1 member, called myPublicMethod. Is this understandable, or do you have further question? I'd gladly help.
0

I think in both approaches you mentioned, When ever object is created using constructor pattern the properties will get copied to its objects. This you mentioned for the 1st approach as the concern. I feel the same will be applied for the second approach also along with your concern in this approach.

We generally go to the second approach you mentioned when ever we want to extend the properties of "MyStack" to some other class.

Lets say i want to extend your class MyStack to MyTest like below

var dummy = function();
dummy.prototype = MyStack.prototype;
var MyTest = function(){
};
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest
var obj = new MyTest();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.