Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've seen a number of different methodologies when it comes to applying class-based inheritance to JS/ECMA-based projects. Over the past several months, I've been applying IIFE Namespaces to my class models when I need classes. This results in a little extra boilerplate code that is easily abstracted for highly dynamic classes. (Make note that I only employ classes when they indeed fit the task.)

In general, I see classes employed in one of the following 4 ways:

Constructor:

function MyClass(arglist) {
    this.property = value;
    this.method = function(){};
}

Prototype:

function MyClass(arglist) {
    this.property = value;
}
MyClass.prototype.method = function(){};

Object.create

Object.create(MyClassPrototype, {prop-list});

IIFE Class

MyClass = (function(){
    function MyClass(arglist) {
        this.property = value;
    }
    MyClass.prototype.method = function(){};

    return MyClass;
}());

Obviously, there tend to be some support functions to reduce keystrokes, such as extend() and/or inherit() helpers. Let me be upfront that I don't generally like the most accepted class libraries (for various reasons), so I've been experimenting with my own methodology. What I've come up with is the following:

Class Module

(function(Class){
    //Private Static Property
    var staticProperty = value;

    //Public Static Function
    Class.staticMethod = function(){}

    //Potentially allows for static construction
    Class.create = function(config){
        //Public Object Member
        this.property = value;
    }

    //So the constructor actually works.
    Class.prototype.class = Class;
    //Public Object Method
    Class.prototype.method = function(){};

    //Allows it to be assigned to a var or Namespace.
    return MyClass;
}(function MyClass(){this.class.create.apply(this, arguments)}));

What I'd like to know is, what are some potential pitfalls to this pattern? Here are some of the advantages that I think this pattern has:

  • The use of private statically scoped functions. In my own experience, this can dramatically improve performance by taking functions out of the constructor that don't need to either a) be there, or b) don't make sense as closures.
  • The ability to use new(), static create(), Object.create() as desired.
  • Doesn't break any standards-required functionality for classes (i.e. new, instanceof, typeof, prototype chain, constructor, etc.)
  • Give every object a reference to their current "class". Not necessary for many things, but I always seem to want it when it doesn't exist.
  • Can utilize the class as a facade for multiple classes without breaking logic or flow. While I haven't used this a lot, it's extremely useful when I do.
  • Hoisting different methods at different times can adjust the benchmarks according to the need for the specific class. For instance, if I need it to construct objects faster, I can hoist a constructor method to the private static level. In contrast, if I need a particular method to perform faster, I can hoist a prototype method to the private static level.
  • Nesting classes is simple
  • Since scoping is so important to JS security, usability and performance metrics, I find this to be the most flexible.
  • I personally find it to be very readable (in general). At a glance, I know whether a method is public or private, static or object.
  • Finally, though very rare, sometimes I need the "class" to have different behaviors when not actually interacting with an object. This pattern allows me to do this with one simple check.

My question here is, since I am quite biased toward this pattern when implementing Class-like behavior, what pitfalls should I be aware of to avoid this becoming an antipattern? Are there any clear reasons to avoid this pattern entirely, aside from bias or convention?

share|improve this question
    
If it helps, I've also done some benchmarking (though it is not complete) with this pattern. It is fairly extensive, but there is a lot more to go: jsperf.com/class-pattern-comparison/3 –  Fuzzical Logic Nov 21 '13 at 17:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.