base-js

A modified version of John Resig's simple classical inheritance that allows for use of the module pattern.

Base.js

An expansion of John Resig's simple js classical inheritance that allows for developing classes using the module pattern, and also introduces a Scope object which is passed between links in the inheritance chain. It also refrains from using protected words.

Right now you can install via NPM: npm install base-js or Bower: bower install base-js, or just download Base.js or Base.min.js from the build folder in the repo if package managers frighten or offend you. At that point including them is as easy as using the AMD / CommonJS module loader of your choice, or loading it directly with a <script> tag.

If you decide that you want to monkey around with the source, note that for development, I'm only using AMD module-loading. To make this CommonJS and global-friendly as well, you'll need to run the build command after you've made your changes. To do this, run the build command - gulp build. You may need to have gulp installed globally, I'm not sure. To do that run npm install gulp -g, and try to build again.

It will output two files: build\Base.js and build\Base.min.js. As I said before, these are compatible with CommonJS and AMD module loaders, and in the event that neither of those are available, it will attempt to register Base as a global variable.

To create an extendable class, simply extend the Base class.

var Vehicle = Base.extend(
    function()
    {
        this.honk = function()
        {
            console.log("Honk honk!");
        };
    }
);
 
var car = new Vehicle();
 
// Writes "Honk honk!" to the console. 
car.honk();

You can then extend this class as well.

var Camry = Vehicle.extend(
    function()
    {
        this.make = 'Toyota';
    }
);
 
var otherCar = new Camry();
 
// Writes "Honk honk!" to the console. 
otherCar.honk();

If you override a method that exists on the parent class, you can access the overridden method by referencing this.base() from within the function scope.

var Hummer = Vehicle.extend(
    function()
    {
        this.honk = function()
        {
            console.log('Beep!');
            this.base();
            console.log('Hoooonk!');
        }
    }
);
 
var compensation = new Hummer();
 
// Writes three lines to the console: 
//  "Beep!" 
//  "Honk honk!" 
//  "Hoooonk!" 
// ...Because you really wanted people to hear that. 
compensation.honk();

Subclasses pass instance of checks for superclasses.

(new Hummer()) instanceof Hummer; // true 
(new Hummer()) instanceof Vehicle; // true 
 
// And then the opposite will fail. 
(new Vehicle()) instanceof Hommer; // false 

The scope object is passed as the only argument into the class scope. You can consider this a container that emulates protected visibility. Any properties or methods are shared down the inheritance chain.

var Person = Base.extend(
    function(scope)
    {
        scope.name = 'Burly Joe';
 
        this.greet = function()
        {
            scope.name + ' says "Hello."';
        };
    }
);
 
var joe = new Person();
 
// Outputs 'Burly Joe says "Hello."' 
joe.greet();
 

The neat thing about this is that you can then reference it in sub-classes.

var Joe = Person.extend(
    function(scope)
    {
        this.greet = function()
        {
            //scope.name is available to me here! 
            scope.name + ' says "Hey guys!"';
        }
    }
);
 
var joe = new Joe();
 
// Outputs 'Burly Joe says "Hey guys!"' 
joe.greet();
 

There is one special case method you can create on the scope object. If you define a construct() method, it will receive all of your constructor arguments.

var NameablePerson = Person.extend(
    function(scope)
    {
        scope.construct = function(name)
        {
            scope.name = name;
        }
    }
);
 
var guy = new NameablePerson('Steve');
 
// Outputs 'Steve says "Hello."' 
guy.greet();

And then, like public facing methods, when overriding scope methods, this.base() references the superclass's method.

var ClothedPerson = NameablePerson.extend(
    function(scope)
    {
        scope.construct = function(nameshirt)
        {
            this.base(name);
            scope.shirt = shirt;
        }
    }
);
 
var lastPerson = new ClothedPerson('Clyde', 'Iron Maiden zip-up hoodie');
 
// Outputs 'Clyde says "Hello."' 
lastPerson.greet();

Um... I think that's it.

Just let me know; submit an issue or submit a pull request.