privaskey, prototype-friendly privacy

by plus5keen

HTML

<!DOCTYPE html>
<html>
    <head>
        <title></title>
    </head>
    <body>
        <h2>Output</h2>
        <div class="output"></div>
        <p>additional output goes to development console</p>
    </body>
</html>

JavaScript

// privaskey
// Simple Prototype-Friendly Privacy
// by Cory Watson

// call privaskey.init(obj) to give obj private data
// call privaskey(obj) to access obj private data
// call privaskey.make() to create a private privacy object for truly private data
// call privaskey.makeFriend(i) to share a privaskey object with another module, allowing it to access your private data
// use multiple privaskey objects to share only a portion of your private data
(function (global) {
    'use strict';

    var idPrefix = '__PRIVID__',
        idCounter = 0,
        idSuffix = '__';
    
    var DEBUG_MODE = global.DEBUG;// || true;
    
    function getId() {
        return idPrefix + String(idCounter++) + idSuffix;
    }

    function make() {
        var lib = [], p, id = getId();

        p = function privacyGet(obj) {
            var o = lib[obj[id]];

            if (o.self === obj) {
                return o.data;
            }
        };

        p.init = function privacyInit(obj) {
            obj[id] = lib.length;
            lib.push({
                self: obj,
                data: DEBUG_MODE ?
                    obj['__PRIVASKEY_DEBUG' + id] = {} :
                    {}
            });
        };

        p.make = make;
        
        p.makeFriend = function (i) {
            if (!i || i === 0) { i = 1; }

            return function makeFriend() {
                if (!i) { return; }
                i--;
                return p;
            };
        };

        p.makeProp = function (key) {
            return function (value) {
                if (typeof value === 'undefined') {
                    return p(this)[key];
                }

                return (p(this)[key] = value);
            };
        };

        return p;
    }

    global.privaskey = make();

}(this));

// Design Note:
// The unique ID per object-privacy-pair isn't strictly necessary, but it
// saves us having to run an equality search for the given object. Once we've
// used the...