Private fields: using prototype, reducing boilerplate (2)

by mbread

JavaScript

//***********************************
// Re-usable code
//***********************************

var PRIVATES = (function () {
    var privateAccess = null;
    var getterSetterCount = 0;
    var module = {};

    // A function to be called form a constructor to create the storage for private fields in an object
    var prepareObject = function (object) {
        var privateStorage = {};
        object.loadPrivateAccess = function () {
            privateAccess = privateStorage;
        }
    }

    // A function to create a getter/setter function that stores its value in a private field
    module.createGetterSetter = function () {
        var propertyName = getterSetterCount++;
        return function () {
            if (typeof this.loadPrivateAccess != "function") prepareObject(this);
            this.loadPrivateAccess();
            try {
                switch (arguments.length) {
                    case 0:
                        return privateAccess[propertyName];
                    case 1:
                        privateAccess[propertyName] = arguments[0];
                        break;
                }
            } finally {
                // Obviously this won't work for reentrant calls, but we're in control of the contents of the getter/setter anyway, so we know it's not reentrant
                privateAccess = null;
            }
        };
    }

    module.createStringifyer = function () {
        return function () {
            if (typeof this.loadPrivateAccess != "function") prepareObject(this);
            this.loadPrivateAccess();
            try {
                return JSON.stringify(privateAccess);
            } finally {
                // Obviously this won't work for reentrant calls, but we're in control of the contents of the getter/setter anyway, so we know it's not reentrant
                privateAccess = null;
            }
        }
    }

    return module;
}());

//***********************************
// Each class (much less...