Proxy object pattern

by Douglas Enas

JavaScript

// defineClass creates an object constructor.
// options: {
//     "constructor": (optional) function to initialize the object
//     "public": object containing the public functions
//     "private": object containing the private functions, only callable by the object itself
// }
var defineClass = function (options) {
    var realClass, // has both public and private functions, and the data
        proxyClass, // has just the public functions
        constructorFunction,
        property,
        createProxyFunction,
        publicProperties = options["public"] || {}, // "public" is a reserved keyword, so can't use options.public
        privateProperties = options["private"] || {}; // same for "private"
    
    // The constructorFunction creates instances of the class we're defining here.
    constructorFunction = function () {
        // Explicitly return an object, instead of using 'this'.
        return new proxyClass(new realClass());
    };
    
    // Use the constructor if defined, otherwise create an empty constructor.
    realClass = options.constructor || function() { };
    
    // Add the public and private properties to the real class's prototype.
    for (property in publicProperties) {
        if (publicProperties.hasOwnProperty(property)) {
            realClass.prototype[property] = publicProperties[property];
        }
    }
    for (property in privateProperties) {
        if (privateProperties.hasOwnProperty(property)) {
            realClass.prototype[property] = privateProperties[property];
        }
    }
    
    // A proxy has a special property referencing the real object it's wrapping.
    proxyClass = function (realObject) {
        this.__realObject__ = realObject;
    };
    // Objects created from constructorFunction will be instances of proxyClass.
    // So assigning the prototype means instanceof will still make sense.
    // e.g. (new MyClass()) instanceof MyClass === true
    proxyClass.prototype =...