A JavaScript class pattern that starts with a function

[2011-10-17] dev, javascript, jslang
(Ad, please don’t block)
There are too many JavaScript class patterns and inheritance APIs out there. Here is another one. The twist: Its core construct is a function, not an object literal.

Example usage:

    var MyClass = function () {
        this.count = 0;
    }
    .extends(SuperClass)
    .proto({
        myMethod: function() {
            this.count += MyClass.CONSTANT;
            // ...
        },
    })
    .class({
        CONSTANT: 123,
    });
We make use of the fact that ECMAScript 5 allows trailing commas in object literals. The class definition starts with a function expression (a function declaration does not allow you to invoke methods) and then invokes methods on it to extend a superclass, add methods and add class properties.

This is the code that makes the above work:

    (function() {
        function copyOwnTo(source, target) {
            Object.getOwnPropertyNames(source).forEach(function(propName) {
                Object.defineProperty(target, propName,
                    Object.getOwnPropertyDescriptor(source, propName));
            });
            return target;
        }

        Function.prototype.extends = function (superClass) {
            var thisProto = Object.create(superClass.prototype);
            // At the very least, we keep the "constructor" property
            // At most, we preserve additions that have already been made
            copyOwnTo(this.prototype, thisProto);
            this.prototype = thisProto;
            return this; // enable chaining
        };

        Function.prototype.proto = function (protoProps) {
            copyOwnTo(protoProps, this.prototype);
            return this; // enable chaining
        }

        Function.prototype.class = function (classProps) {
            copyOwnTo(classProps, this);
            return this; // enable chaining
        }
    }());
Note: This pattern is more a proof of concept than something I would use in practice. But I like that this kind of thing can be done in JavaScript.

Related reading:

  1. Class Definition Pattern Using Object Extension Literals” by Allen Wirfs-Brock [inspiration for this blog post]