Javascript-fastClass
A faster and easier way to define Javascript Prototypal Inheritance: classes
and mixins
Performance tests
- Among
popular libraries define + usage
- 3 classes and 3 methods * 500 instances each Fastest libraries define + usage
- 3 classes and 3 methods * 500 instances eachFastest libraries define only
- 3 classes and 3 methods * 1 instances each- Unit tests - so you can see it just works
Syntactic sugar
var Vehicle = Function;//optionally specify extra mixins i.e. , Wheels); var Car = Vechicle;//optionally specify extra mixins whose prortotype members will be copied to Car.prototype //Define the Engine mixin { //this constructor will be automatically called when creating any class using it //(including derrived classes). i.e. new Car() in this example thispowerSource = 'petrol';//these properties will be added to every Car instance thiscmc = 1400;// i.e. var c= new Car(); c.cmc = 1400 thishorsePower = 140;} var toyota = "toyota prius" "red";//creating a new CartoyotapowerSouce; //petroltoyotapowerSource = 'electric'; //changing the powerSource property toyota;//returns truetoyota; //Drawing a red car. //Drawing a tyota prius vechicle.
Why yet another library?
Native javascript inheritance is a pin in the ass. Even if you understand it perfectly it still requires some hideous repetivie code.
There are a lot of libraries which aim to help you with such that, but the main question is:
What is the fastest
vs most convenient
(also known as: with the most sugar
) to create Prototypal Inheritance
with?
When to use it?
You might want this library
- when you can't use a language that
compiles
into javascript code. - because it is fast
- you love
writing less - doing more!
e.g. Google Closure, TypeScript, Coffee Script etc.
What is it?
FastClass is a very tiny library (<1.5KB minified and gzipped) that helps you quickly derrive your classes
so to speak.
It comes in two flavours:
Function.prototype.fastClass(creator)
- sets theBase.prototype
to thecreator
function and then callsnew creator(this.prototype, this)
{ thissomePrototypeMethod1 = ...; thissomePrototypeMethod2 = ...; } }
Function.prototype.inheritWith(creator)
- recommended returns aplain object
containing the members of the new prototype, including the constructor itself
It makes usage of proto on all new browsers (which makes it blazing fast) except Internet Explorer <= 10
and maybe other ancient browsers where it fallbacks to for (var key in obj)
statement.
Note __proto__
will become standard in ECMAScript 6
{ return somePrototypeMethod1: ... somePrototypeMethod2: ... }
whereas baseCtor
is the function we want to inherit and base is it's prototype (baseCtor.prototype
that is).
How to use it?
Defining the base "class"
var { thisname = name; Function;// since this is a top function, we need to call initMixins to make sure they will be initialized.}Figureprototype { console; }
.define
sugar
You can define the first class' constructor function
(same as above but with sugar syntax) as following:
var { thisname = name; Function;// since this is a top function, we need to call initMixins to make sure they will be initialized.}
The define
function copies all the members of the returned object to the function.prorortpe
(A.prototype
) and returns it (A
)
Function.define
even better sugar - recommended
This way we don't need to call Function.initMixins(this)
as it will be automatically called for us
var A = Function
Alternatively you can pass an object with the costructor function specified (similar syntax to .inheritWith
)
var A = Function
All of the above methods are doing the same thing. You decide which one better suits you.
Inheritance
A classical example to use inheritance when you have a base class called Figure
and a derrived class called Square
.
.fastClass
flvaour
To define the derrived class
Square:
var Square = Figure
.inheritWith
flavour
To define the derrived class
Square:
var Square = Figure
As you can see in both cases the definition is pretty simple and very similar.
However the .inheritWith
flavour comes with about 5-15% performance boost
depending on the actual browser and number of members.
That is because we are simply setting __proto__
with the BaseClass.prototype for those browsers who support it (all nowdays browsers except IE<=10
)
The constructor
In both cases we the constructor
is the function that is returned as the derrived class' constructor
.
The constructor
is optional and we should only add it when we have some custom code as both functions will add it for us otherswise.
Usage
Whichever flavour you choose the code usage is the same. Firstly you need to instantiate the Constructor with the new
operator:
var figure = "generic";figure;//figure genericvar square = "10cm square" 10;figure; //square with length 10//figure 10cm square
Mixins support
Mixins are some grouped functionalities that you can add to a class
without inheritance
You can learn more about mixins
vs inheritance
on this post.
We can define mixins as
- an
object
containing functions - a
function
which will be executed for every instance of the class that is using it- The
prototype
of the function will be automatically copied to theclass.prototype
that are using it
- The
Another Example
// Animal base class { // Private {} {} // Privileged - on instance this{} this{} Function;};
Alternatively the above can be defined as:
var Animal = Function;
Or even simpler as an object providing the constructor
:
var Animal = Function;
The function Animal
is the function
given as first parameter.
It acts as the constructor, which is invoked when an instance is created:
var animal = ; // Create a new Animal instance
Spicing it up with inheritance and mixins
We can typically define a move
action which is a set of methods grouped in our Move mixin
Defining the mixin
{//define the constructor of the mixin. This will be automatically called for every instance in the constructor of the class that is using this mixin thisposition = x: 0 y: 0;};
Move
mixin
Adding Inheritance and using the .inheritWith
flavour
Usage using [[constructor]].inheritWith( function(base, baseCtor) { return {...} }, mixins )
- that function should return
methods for the derrived prototype
Example
// Extend the Animal class with inheritWith flavorvar Dog = Animal;//specify any extra mixins to be added to the Dog's prototype
Create an instance of Dog
:
var husky = ;husky; // Animal::method1// Dog::method1 husky;// Dog::I scare you' /// testing the mixin:husky; // Call the method of the mixin. // Position: {x: 0, y: 0} husky; husky;// Position: {x: 10, y: 20} husky;husky;// Position: {x: 0, y: 0}
.fastClass
flavour
Same as above using [[constructor]].fastClass( function(base, baseCtor) { this.m = function {...} ... } )
- that function populates
the derrived prototype
Every class definition has access to the parent's prototype via the first argument passed into the function. The second argument is the base Class
itself (its constructor i.e. Animal
in our case):
// Same as above but Extend the Animal class using fastClass flavorvar Dog = Animal;
Static members
You can sometime extend a constructor or a function with some static methods
In order to do so you need to call .defineStatic({...})
var {}typeof FloadData // returns functionF //call the static function
This can be easily mixed with Function.define
var F = Function
abstract
methods
Mixin The Function.initMixins
will always check for duplicate members that are already defined in the object i.e. the class defines a member whith the same name, or another mixin defines it.
If such collision is found an exception will be thorwn when using the debug version of the library. Using the .min
file there is no error and the member will be overriden.
However in order to prevent this exception you can define a function as abstract with .defineStatic(obj)
:
var Animal = Function;
Abstract methods sugar
var f = Function;;//will trigger a failed assert with message "Not implemented"var g = Function;;//will trigger a failed assert with message "Custom not implemented message"fabstract === true;//truevar h = Function;;//will call the given function and then will trigger a failed assert with message "Not implemented"var j = Function;;//will call the given function and then will trigger a failed assert with message "Custom not implemented message"
Where to get it from?
Beside GitHub, you can download it as a Nuget package
in Visual Studio fromhere
Install-Package Javascript-FastClass
What's next?
Do you have a better & faster way? Share it! We would love to seeing creativity in action!