Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Prototypes and Private State

DZone's Guide to

Prototypes and Private State

· Web Dev Zone
Free Resource

Get deep insight into Node.js applications with real-time metrics, CPU profiling, and heap snapshots with N|Solid from NodeSource. Learn more.

 

"private" state in JavaScript means using local state in a constructor function and returning methods which are in scope of that local data. This pattern is not compatible with prototypes.

The following is reposted from Jake Verbaten's blog, Raynos

 

An example:

Live Example

function Parent() {
    // a is private
    var a = 42;

    this.printA() {
        console.log(a);    
    }
}

Parent.prototype.doubleA = function() {
    // How do I access a?
}

There is simply no way you can use "private" state and prototypes because here "private" means local variables inside a constructor.

This is simply the wrong way to do private state. A better solution for private state is a Name. The following examples will use pd to give us an implementation of a Name A Name is a function, given any key will return an object attached to that key.

You can only get that object if you have both the Name and the key. Let's look at an example:

Live Example

var Parent = (function () {
    // "private" Name
    var privates = pd.Name();

    Parent.prototype.doubleA = function() {
        // _ is the unique object
        var _ = privates(this);
        _.a = _.a * 2;
    };

    Parent.prototype.printA = function () {
        // print from the unique object for this instance
        console.log(privates(this).a);    
    };

    return Parent;

    function Parent() {
        // set a on the unique object for this instance
        privates(this).a = 42;
    }
})();

var p = new Parent;
p.doubleA();
p.printA();

Now we can give this a bit of sugar and have an inheritance mechanism using these private Names. Using a function like klass

Live Example:

var Parent = klass(function (privates) {
    // this becomes Parent.prototype
    // Parent becomes the constructor function
    return {
        constructor: function () {
            privates(this).a = 42; 
        },
        printA: function () {
            console.log(privates(this).a);
        }
    };
});

var Child = klass(Parent, function (privates, $super) {
    // the privates Name object is the same as the one used in Parent
    // This becomes Child.prototype. 
    // Child.prototype will inherit from Parent.prototype
    // Child becomes the constructor
    return {
        constructor: function () {
            // $super === Parent.prototype
            $super.constructor.call(this);   
        },
        doubleA: function () {
            var _ = privates(this);
            _.a = _.a * 2;   
        }
    };  
});

var c = new Child;
c.doubleA();
c.printA();

Note that using privates(this).a over this._a has a run-time overhead and a memory overhead.

One needs to choose between "do I want efficient code" or "do I want real hidden state".

 

 

Node.js application metrics sent directly to any statsd-compliant system. Get N|Solid

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}