In my humble opinion the smallest classical OOP pattern is as follows:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
You may then use it as:
var Rectangle = defclass({
constructor: function (width, height) {
this.height = height;
this.width = width;
},
area: function () {
return this.width * this.height;
}
});
The only problem is that this doesn't support inheritance which is why I created `augment`. While creating `augment` I kept the following things in mind:
1. I didn't want to use a `for..in` loop to copy all the methods of the "class". Hence I used a function instead of an object to model the prototype.
2. Using a function instead of an object to model the prototype is similar to the module pattern. In addition you can create private static properties of a class (such as configuration) easily.
3. I wanted `augment` to work for both the [constructor pattern and the prototypal pattern](http://stackoverflow.com/a/16872315/783743) which is why `base` may be either a function or an object.
4. I wanted `augment` to be able to create singleton instances (again in the spirit of the prototypal pattern of prototypal inheritance). Hence I simply return the prototype if the "class" doesn't have a constructor.
Keeping these points in mind I added 4 more lines to the `defclass` function to create `augment`:
function augment(base, body) {
var uber = typeof base === "function" ? base.prototype : base;
var prototype = Object.create(uber);
body.apply(prototype, [].slice.call(arguments, 2).concat(uber));
if (!prototype.hasOwnProperty("constructor")) return prototype;
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
The above function is essentially the `augment` function in my GitHub repository minus the following features:
1. It's not defined as a method of `Function.prototype` or `Object.prototype`. Hence you can't call it as a method on a function or an object. I added this feature for flexibility of style. In retrospect I believe that it's unnecessary and hence I'll remove it.
2. It won't work in browsers which don't support and haven't patched `Object.create`. I understand that the patch my library provides is incomplete. In my defense I never thought that it would become infamous overnight. I'll fix this as well.
3. It doesn't use `bindable`, `callable` and other functional features I commonly use in my code. When I created `augment` I never expected many people to use it. Hence I put in all the functional features I commonly use in all my programs.
4. It doesn't use the `{}.hasOwnProperty.call` hack. Again I programmed defensively in my library. However I doubt that JavaScript programmers usually create classes which don't inherit from `Object.prototype`. Hence I'll remove that hack as well.
In short I'll remove all the unnecessary features from `augment` that I commonly use and deliver the smallest classical OOP library as promised.
1. I didn't want to use a `for..in` loop to copy all the methods of the "class". Hence I used a function instead of an object to model the prototype.
2. Using a function instead of an object to model the prototype is similar to the module pattern. In addition you can create private static properties of a class (such as configuration) easily.
3. I wanted `augment` to work for both the [constructor pattern and the prototypal pattern](http://stackoverflow.com/a/16872315/783743) which is why `base` may be either a function or an object.
4. I wanted `augment` to be able to create singleton instances (again in the spirit of the prototypal pattern of prototypal inheritance). Hence I simply return the prototype if the "class" doesn't have a constructor.
Keeping these points in mind I added 4 more lines to the `defclass` function to create `augment`:
The above function is essentially the `augment` function in my GitHub repository minus the following features:1. It's not defined as a method of `Function.prototype` or `Object.prototype`. Hence you can't call it as a method on a function or an object. I added this feature for flexibility of style. In retrospect I believe that it's unnecessary and hence I'll remove it.
2. It won't work in browsers which don't support and haven't patched `Object.create`. I understand that the patch my library provides is incomplete. In my defense I never thought that it would become infamous overnight. I'll fix this as well.
3. It doesn't use `bindable`, `callable` and other functional features I commonly use in my code. When I created `augment` I never expected many people to use it. Hence I put in all the functional features I commonly use in all my programs.
4. It doesn't use the `{}.hasOwnProperty.call` hack. Again I programmed defensively in my library. However I doubt that JavaScript programmers usually create classes which don't inherit from `Object.prototype`. Hence I'll remove that hack as well.
In short I'll remove all the unnecessary features from `augment` that I commonly use and deliver the smallest classical OOP library as promised.