1
\$\begingroup\$

Background

I like to code JavaScript in a typical style with "classes" and inheritance. My goal was to create an easy way to make inheritance available and keep classes that inherits from others clean. Also I like to use the module pattern and uses its look and feel.

My solution

I hope the code is self-explanatory. I'm using it in all my newer projects and it seems to work fine.

 if(typeof(SimpleJSLib)==='undefined'){
     var SimpleJSLib = {}; // define namespace
 }
 SimpleJSLib.BaseObject = function(){
     // returns an object you wether can inherit from or instantiate it
     var createInheritObject = function(inheritFunctions){
         return {
             // instantiate the current class
             // iterates through all functions which the class inherits from and calls them
             construct : function(){
                 var me = {}, _protected = {};
                 for(var i = 0; i < inheritFunctions.length; i++){
                     me = inheritFunctions[i].call(me, me, _protected);
                     if(typeof(me)==='undefined'){
                         throw 'Inherit function did not return "me"';
                     }
                 }
                 // if a constructor is defined we call them and deliver the arguments this function was called with
                 if(typeof(_protected.construct)!=='undefined'){
                     _protected.construct.call(me, arguments);
                 }
                 return me;
             },
             // clones the pointers to the functions you inherit from
             // and returns another object you can instantiate or inherit from
             inherit : function(inheritFunction){
                 var _inheritFunctions = inheritFunctions.slice(0); // clone
                 _inheritFunctions.push(inheritFunction);
                 return createInheritObject.call(window, _inheritFunctions);
             }
         };
     };

     return {
         // allows you to inherit directly from BaseObject
         inherit : function(inheritFunction){
             // this is the first call of the function, so the the inheritFunctions array just contains one function
             return createInheritObject.call(window, [inheritFunction]);
         }
     }
 }();

Questions

Is there any good argument why I shouldn't use this code snippet? How about performance? Is there anything I could make better?

Examples

Just a few simple ones.

var MyClass = SimpleJSLib.BaseObject.inherit(function(me, _protected){
    // protected
    _protected.myValue = 'value';
    _protected.doSomething = function(){
        console.log('something')
    };
    // public
    me.getMyValue = function(){
        return _protected.myValue;
    }
    return me;
});
var MySubClass = MyClass.inherit(function(me, _protected){
    me.anotherFunction = function(){
        _protected.doSomething();
    }
    return me;
});
var myClassInstance = MyClass.construct();
console.log(myClassInstance.getMyValue());
var mySubClassInstance = MySubClass.construct();
console.log(mySubClassInstance.anotherFunction());

Using the constructor

var MyClass = SimpleJSLib.BaseObject.inherit(function(me, _protected){
    _protected.valueOne = null;
    _protected.valueTwo = null;
    _protected.construct =  function(parameters){
        _protected.valueOne = parameters[0];
        _protected.valueTwo = parameters[1];
    };
    return me;
});
var myClassInstance = MyClass.construct('valueOne', 'valueTwo');

Singelton

var Singelton = SimpleJSLib.BaseObject.inherit(function(me, _protected){
    return me;
}).construct(); // mention the construct!
\$\endgroup\$
  • 1
    \$\begingroup\$ Reinventing the wheel. jQuery and underscore for example both have .extend methods that take care of inheritance see how those are implemented. Also, look at how TypeScript handles it. Also, look at Douglas Crockford's blog posts on how to simulate classical inheritance. Also, classical inheritance in javascript is rarely used because prototypical inheritance is generally better (share functionality). \$\endgroup\$ – Benjamin Gruenbaum Feb 22 '13 at 13:56
  • \$\begingroup\$ jQuery.extend do not support a protected scope as far as I know. I haven't looked at the other frameworks. "Also, classical inheritance in javascript is rarely used because prototypical inheritance is generally better (share functionality)". What do you mean with "share functionality"? \$\endgroup\$ – roccosportal.com Feb 22 '13 at 14:14
  • \$\begingroup\$ Why is inheritance so useful? You generally use inheritance to indicate different objects are similar, ie that one object is a superset of another object. To use a classic example every Dog is an Animal. Inheritance lets you share functionality between Dog and Animal, and to treat Dogs like Animals (Polymorphism), since javascript is a dynamic language the second advantage is no longer a concern, I can treat any object whichever way I'd like. Since functions are objects in js I can also apply Animal functionality on Dog without having to be explicit about it Animal.doAnimalStuff.apply(dog)) \$\endgroup\$ – Benjamin Gruenbaum Feb 22 '13 at 14:42
  • \$\begingroup\$ Yes, sure. But inheritance also allows you to reuse functionalities from your parents. To treat an dog like an animal is possible in my implementation. Have a look in example one. You could call mySubClassInstance.getMyValue();. (Oh, there was a bug in the example that might explains the misunderstanding. var mySubClassInstance = MySubClass.construct() is the correct call) \$\endgroup\$ – roccosportal.com Feb 22 '13 at 14:58
  • \$\begingroup\$ So does prototypical inheritance, methods of your parents are accessible to you. This is really not a subject for discussion in comments, you're more to the stackoverflow javascript chat where we can discuss this: chat.stackoverflow.com/rooms/17/javascript \$\endgroup\$ – Benjamin Gruenbaum Feb 22 '13 at 15:59
2
\$\begingroup\$

From some staring at your code:

  • Do not declare var in an if block, it gives the wrong impression. I would just declare it on top, something like this:

    //Define namespace
    var SimpleJSLib;
    SimpleJSLib = SimpleJSLib || {}; 
    

    As far as naming, since SimpleJSLib is not a constructor, it should not start with capital S. The name JSLib is not very informative beyond what language it is writen in..

  • I know that for some _ in _protected means "private", but I agree with Crockford that this convention should be avoided
  • Now a big one: you broke support for instanceof operator, that's just wrong
  • Furthermore, you kind of broke support for prototype, you are also not using hasOwnProperty anywhere when you construct objects
  • And, JS has a perfectly valid constructor, but you decided to have your own construct
  • Finally, this will be messy once you want to start serializing with JSON

Honestly, read this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript and abandon your code. I would not want to maintain code that relies on this.

\$\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.