5
\$\begingroup\$

I have a simple class inheritance in JS:

var Class = function(){};

Class.extend = function(){

    var Extended = function(constructor){

        function extend_obj(destination, source) {
            for(var property in source){
                if(typeof source[property] === "object" && source[property] !== null && destination[property]){ 
                    extend_obj(destination[property], source[property]);
                }else{
                    destination[property] = source[property];
                }
            }
        };

        extend_obj(Extended.prototype, constructor);

        this.constructor.init();
    };

    Extended.init = function(){};

    for(var key in this.prototype){
        Extended.prototype[key] = this.prototype[key];
    }

    Extended.prototype.constructor = Extended;

    for (var key in this) {
        Extended[key] = this[key];
    };

    return Extended;
};

Which allow me to do so:

var SubClass = Class.extend();

SubClass.static_property = "a static property";

SubClass.static_method = function(){
    return "a static method";
};


SubClass.prototype.a_new_property = "something new"; //instance method

var instance = new SubClass({
    name: "custom name"
});

SubClass.init = function(){
    //custom constructor
};

this.constructor.static_method_or_property //call instance method

I need:

  • multiple inheritance
  • the possibility to use module pattern

There's a cleaner/better/faster way to do that?

\$\endgroup\$
4
+50
\$\begingroup\$

First of all, it seems like you're reinventing the wheel here. You didn't provide any context for what this is for so I'll try to cover all bases.

If you are using this as part of a bigger project, I'd recommend abandoning this approach and picking up something like Prototype.js or maybe Ember.js if you're ambitious. Alternatively, take a look at how CoffeeScript does it. CoffeeScript's underlying JS is pretty messy but it's significantly simpler than yours AND supports inheritance.

If this is just an educational exercise, I can point out a few problems with your code that I see.

  1. extend_obj(Extended.prototype, constructor);
    • This seems to be copying the instance's properties onto the class prototype. This doesn't make much sense as the instance's properties should be separate.
  2. var instance = new SubClass({ name: "custom name" })
    • This actually instantiates an Extended (aka SubClass) object with no instance properties and modifies the Extended prototype to have a name property of "custom name". This is very strange behavior.

In general, when trying to emulate Classes in JS, the prototype is where instance methods go or, possibly, default values for properties. However, an instance (created with new) should have no effect on it.

\$\endgroup\$
  • \$\begingroup\$ I'd also think you shouldn't force classical OOP theme's and instead use a more functional programming approach. \$\endgroup\$ – benvds Aug 30 '12 at 9:06
1
\$\begingroup\$

JavaScript's prototypal inheritance has some advantages over classical inheritance. As mentioned above, if you really need to use classical inheritance, its far better to go with the libraries as suggested, or even change language (such as to coffeescript or even Dart).

I would highly recommend you read up a little on prototypal inheritance, it may well be that you can solve your needs with it.

Try here: Mozilla Developer Network - Prototypal Inheritance

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.