Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Multiple object extend pattern in JavaScript

DZone's Guide to

Multiple object extend pattern in JavaScript

· Web Dev Zone ·
Free Resource

Bugsnag monitors application stability, so you can make data-driven decisions on whether you should be building new features, or fixing bugs. Learn more.

I was doing some research about JavaScript Inheritance patterns realizing there are many different approaches and divided opinions which pattern or method is better. There is no widely accepted bulletproof pattern that will cover every possible scenario, probably because It all depends what you trying to achieve.

I needed a pattern that can accept and extend multiple objects. Usually is very common to see one object that extends another object extend(object1, object2) but I needed pattern that accepts multiple objects like extend(object1, object2, object3). So I decided to make one.

I used Douglas Crockford - Prototypal Inheritance logic, temporally function -> Object.prototype -> new object plus looping inside every object to copy all the methods.

The first pattern accepts only objects:

function extend() {

    var i = arguments.length;

    function F() {}

    while (i--) {

        for (var m in arguments[i]) {
            F.prototype[m] = arguments[i][m];

        }

    }

    return new F();

}

I also made the second pattern in case you want to use function for storing methods.It is highly unlikely that you will use the function just for storing methods, but anyway here is the pattern.

function extendAll() {

    var i = arguments.length;

    function F() {}

    function N() {}

    while (i--) {

        for (var method in arguments[i]) {
            F.prototype[method] = arguments[i][method];

        }

        if (typeof arguments[i] !== "object") {
            N.prototype = new arguments[i]();
            for (var m in N.prototype) {
                F.prototype[m] = N.prototype[m];

            }
        }

    }

    return new F();

}

From the preliminary tests, this pattern should work even in IE 5.5.

Sometimes it can be handy to merge objects or to divide one object in smaller units to increase modularity. Many modern JS Frameworks have one object that holds everything, dividing that object into smaller logical components(objects) can be helpful.

Two months ago I made picoCSS small JS framework for making webkit apps. I will rewrite the picoCSS to demonstrate the functionality of this pattern. Many JS framework have modules like: selector engine, css, animation, other DOM methods, ajax, events … The intention behind this pattern is to merge just the objects(modules) that we need.

Here is picoCSS original and viewed with Object Auto Documentation. Everything is stored inside the object p. The goal is to brake picoCSS several objects like selector, events, animation …

And picoCSS after:

var selector = {

    select: function (selector) {
        this.value = Array.prototype.slice.call(document.querySelectorAll(selector));
        return this;
    }
};

var loop = {
    each: [].forEach,
    map: [].map
};

var css = {
    css: function (v) {
        this.value = this.each.call(this.value, function (i) {
            i.style.cssText = v;
        });
        return this;
    },

    att: function (a, v) {
        this.value = this.each.call(this.value, function (i) {
            i.setAttribute(a, v);
        });
        return this;
    }
};

var animation = {
    animate: function (time, scale, rotate, rotateX, rotateY, translateX, translateY, skewX, skewY) {
        this.value = [].forEach.call(this.value, function (i) {
            i.style.cssText = '-webkit-transition: all ' + time + 's ease-in-out; -webkit-transform: scale(' + scale + ') rotate(' + rotate + 'deg) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg) translate(' + translateX + 'px, ' + translateY + 'px) skew(' + skewX + 'deg, ' + skewY + 'deg)';
        });
        return this;
    }
};

var events = {
    on: function (type, fn) {
        this.value = this.each.call(this.value, function (i) {
            i.addEventListener(type, fn, false);
        });
        return this;
    }

};

Now we can rebuild picoCSS like this: var p = extend(selector, css, loop, events);

The working demo.

In this way we loaded just the objects and methods that we need. This particular case dividing the object has little sense because we have super small library. But in other bigger projects dividing the logic can be very useful not just for increasing modularity but also for decreasing the memory consummation. We can even make different files for every object and load only the files that we use. Naturally we should be careful not to make to many HTTP requests.

Here are some I tests I made

Your comments and suggestions about improving this pattern are welcomed.

From http://www.vcarrer.com/2011/06/multiple-object-extend-pattern-in.html

Monitor application stability with Bugsnag to decide if your engineering team should be building new features on your roadmap or fixing bugs to stabilize your application.Try it free.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}