Socket
Socket
Sign inDemoInstall

private

Package Overview
Dependencies
0
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    private

Utility for associating truly private state with any JavaScript object


Version published
Maintainers
1
Install size
13.2 kB
Created

Readme

Source

private Build Status

A general-purpose utility for associating truly private state with any JavaScript object.

Installation

From NPM:

npm install private

From GitHub:

cd path/to/node_modules
git clone git://github.com/benjamn/private.git
cd private
npm install .

Introduction

In JavaScript, the only data that are truly private are local variables whose values do not leak from the scope in which they were defined.

This notion of closure privacy is powerful, and it readily provides some of the benefits of traditional data privacy, a la Java or C++:

function MyClass(secret) {
    this.increment = function() {
        return ++secret;
    };
}

var mc = new MyClass(3);
console.log(mc.increment()); // 4

You can learn something about secret by calling .increment(), and you can increase its value by one as many times as you like, but you can never decrease its value, because it is completely inaccessible except through the .increment method. And if the .increment method were not available, it would be as if no secret variable had ever been declared, as far as you could tell.

This style breaks down as soon as you want to inherit methods from the prototype of a class:

function MyClass(secret) {
    this.secret = secret;
}

MyClass.prototype.increment = function() {
    return ++this.secret;
};

The only way to communicate between the MyClass constructor and the .increment method in this example is to manipulate shared properties of this. Unfortunately this.secret is now exposed to unlicensed modification:

var mc = new MyClass(6);
console.log(mc.increment()); // 7
mc.secret -= Infinity;
console.log(mc.increment()); // -Infinity
mc.secret = "Go home JavaScript, you're drunk.";
mc.increment(); // NaN

Another problem with closure privacy is that it only lends itself to per-instance privacy, whereas the private keyword in most object-oriented languages indicates that the data member in question is visible to all instances of the same class.

Suppose you have a Node class with a notion of parents and children:

function Node() {
    var parent;
    var children = [];

    this.getParent = function() {
        return parent;
    };

    this.appendChild = function(child) {
        children.push(child);
        child.parent = this; // Can this be made to work?
    };
}

The desire here is to allow other Node objects to manipulate the value returned by .getParent(), but otherwise disallow any modification of the parent variable. You could expose a .setParent function, but then anyone could call it, and you might as well give up on the getter/setter pattern.

This module solves both of these problems.

Usage

Let's revisit the Node example from above:

var p = require("private").makeAccessor();

function Node() {
    var privates = p(this);
    var children = [];

    this.getParent = function() {
        return privates.parent;
    };

    this.appendChild = function(child) {
        children.push(child);
        var cp = p(child);
        if (cp.parent)
            cp.parent.removeChild(child);
        cp.parent = this;
        return child;
    };
}

Now, in order to access the private data of a Node object, you need to have access to the unique p function that is being used here. This is already an improvement over the previous example, because it allows restricted access by other Node instances, but can it help with the Node.prototype problem too?

Yes it can!

var p = require("private").makeAccessor();

function Node() {
    p(this).children = [];
}

var Np = Node.prototype;

Np.getParent = function() {
    return p(this).parent;
};

Np.appendChild = function(child) {
    p(this).children.push(child);
    var cp = p(child);
    if (cp.parent)
        cp.parent.removeChild(child);
    cp.parent = this;
    return child;
};

Because p is in scope not only within the Node constructor but also within Node methods, we can finally avoid redefining methods every time the Node constructor is called.

Now, you might be wondering how you can restrict access to p so that no untrusted code is able to call it. The answer is to use your favorite module pattern, be it CommonJS, AMD define, or even the old Immediately-Invoked Function Expression:

var Node = (function() {
    var p = require("private").makeAccessor();

    function Node() {
        p(this).children = [];
    }

    var Np = Node.prototype;

    Np.getParent = function() {
        return p(this).parent;
    };

    Np.appendChild = function(child) {
        p(this).children.push(child);
        var cp = p(child);
        if (cp.parent)
            cp.parent.removeChild(child);
        cp.parent = this;
        return child;
    };

    return Node;
}());

var parent = new Node;
var child = new Node;
parent.appendChild(child);
assert.strictEqual(child.getParent(), parent);

Because this version of p never leaks from the enclosing function scope, only Node objects have access to it.

So, you see, the claim I made at the beginning of this README remains true:

In JavaScript, the only data that are truly private are local variables whose values do not leak from the scope in which they were defined.

It just so happens that closure privacy is sufficient to implement a privacy model similar to that provided by other languages.

Keywords

FAQs

Last updated on 19 Feb 2014

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc