Skip to main content
6 of 14
added 32 characters in body

Are there any apparent issues with using this pattern?

Since the original post, I have explored further regarding this pattern. In an effort to fix one self-percieved flaw (the lack of ability of prototype methods to access private object members), I have revised this Class pattern. As no one has responded regarding the pattern, I am offering a bounty.

In general, only people with a high level of expertise in JavaScript will probably be able to review this to my requirements. To be clear, here are my requirements:

  • I am not looking for a review that utilizes convention as its primary argument.
  • Code style should only be a factor, if and only if it can keep the pattern intact:
    • All scopes must maintain their accessibility to the other scopes.
  • Clear and Concise review regarding potential security issues.
  • Verifiable performance statistics (if this is one of your review's arguments).
  • Supplemental code and reasoning (for instance, where one would use Object.freeze() or places to consider validation).
  • Other patterns to consider, if they can meet the scoping guidelines.

Please, keep in mind that this is an abstract pattern. The pattern works, though the code utilizes pseudocode.

[var | Namespace.]ClassName = (function(Class) {
    var privateAccess = false;


    /* Any static(class-wide) privates go here */        
    var privateMethod = function() {
        return 'I\'m doing something privately';
    };
    

    /* The class prototype */
    Class.prototype = {};  // or new BaseClass();
    Class.prototype.propertyName = function(value) {
        var returnValue;
        // Unlock private Access
        privateAccess = true;
        
        // Forward the property access
        returnValue = this.privateAccessFunction('propertyName', value);

        // Lock it back up again!
        privateAccess = false;
        return returnValue;
    };
    // Lock the function, so it can't be modified.
    Object.freeze(Class.prototype.propertyName);
    // Optional: Lock the prototype


    /* The class constructor */
    Class.instance = function(config) {
        // Fail if called without using new!
        if (!this instanceof Class)
            return undefined;
 
        // So derivative classes don't share privates
        if (config) {
            var myPrivateMembers = {
                propertyName: 'value'
            };
        
            Object.defineProperty(
                this, 
                'privatePropertyAccess',
                {
                    //This is the actual Getter/Setter
                    // P.S. I like chainable properties
                    value: function(name, value) {
                        // Protects our function from call(obj)
                        if (!privateAccess || !this instanceof Class)
                            return undefined;

                        if (name !== undefined && typeof name === 'string') {
                            if (value !== undefined) {
                                privateMembers[name] = value;
                                return this;
                            }
                            return privateMembers[name];
                        }
                        return undefined;
                    },
                    writable: false,
                    configurable: false,
                    enumerable: false
                }
            });
        }
    };

    // So that we get the Class back
    return Class;
}([Namespace.]ClassName = [Namespace.]ClassName || function(config){
    if (this instanceof [Namespace.]ClassName)
        return [Namespace.]ClassName.instance.call(this, config);
})

After much research, I've determined that I really like this pattern for the following reasons:

Debugging (in Chrome)

  1. ClassNames are clear without having to open the object (even for private Classes).
  2. They remain this way even after minifying with several libraries.

Object Advantages

  1. Object has access to Object Privates & Static/Class Privates
  2. Object controls which private data to expose to Prototype Methods.
  3. Private data may be locked/unlocked on a per method basis.

Prototype Advantages

  1. Prototype Methods have safe access to its own private members.
  2. Prototype Methods are chainable.
  3. Prototype Methods are only defined once. (if modifying the prototype in a constructor, it gets modified every time the constructor runs)
  4. Prototype Methods have access to static private members.

Known Disadvantages

  1. Classes are a little heavier.
  2. PrivateAccess is not thread-safe(the privateAccess variable is static). This should be fine for synchronous code, however.
  3. Derivative classes must conform to a similar pattern (privateAccess and accessPrivateMember())

Final Note

In all of my years, this class pattern is the closest I've ever gotten to classical OOP, without losing any benefit that ECMAScript/JavaScript has. Additionally, it doesn't seem to require additional extension functions. Further, it doesn't inhibit the use of any other type of inheritance that JS provides. While this wasn't the goal, at the time, it is certainly a consideration for me.