JavaScript is a class-free, object-oriented language, and as such, it uses Prototypal inheritance instead of Clas Sical inheritance. This can is puzzling to programmers trained in conventional object-oriented languages like C + + and Java. JavaScript ' s Prototypal inheritance have more expressive power than classical inheritance, as we'll see presently.
But first, why does we care about inheritance in all? There is primarily and reasons. The first is type convenience. We want the language system to automatically cast references of similar classes. Little Type-safety is obtained from a type system which requires the routine explicit casting of object references. This is the critical importance in strongly-typed languages, but it's irrelevant in loosely-typed languages like Javascrip T, where object references never need casting.
The second reason is code reuse. It is very common to has a quantity of objects all implementing exactly the same methods. Classes make it possible to create them all from a single set of definitions. It is also common to has objects that was similar to some other objects, but differing only in the addition or Modificati On a small number of methods. Classical inheritance are useful for this but prototypal inheritance are even more useful.
To demonstrate this, we'll introduce a little sugar which would let us write in a style that resembles a conventional CLA Ssical language. We'll then show useful patterns which is not available in classical languages. Then finally, we'll explain the sugar.
Classical inheritance
First, we'll make a Parenizor class that would have the set and get methods for its value, and a Tostri Ng method that would wrap the value in Parens.
functionParenizor (value) { This. SetValue (value);} Parenizor.method (' SetValue ',function(value) { This. Value =value; return This;}); Parenizor.method (' GetValue ',function () { return This. Value;}); Parenizor.method (' ToString ',function () { return' (' + This. GetValue () + ') ';});
The syntax is a little unusual, but it's easy-to-recognize the classical pattern in it. The method takes a method name and a function, adding them to the class as a public method.
So now we can write
New Parenizor (0= myparenizor.tostring ();
As you would expect, myString is "(0)".
Now we'll make another class which would inherit from Parenizor, which are the same except that it tostring< /c7> method would produce " -0-" if the value is zero or empty.
function Zparenizor (value) { this .setvalue (value);} Zparenizor.inherits (Parenizor); Zparenizor.method ( ' toString ', function () { if ( .getvalue () { return this . Uber (' toString ' ); return " -0-"
The inherits method is similar to Java ' s extends. The Uber method is similar to Java's super. It lets a method call a method of the parent class. (the names has been changed to avoid reserved word restrictions.)
So now we can write
New Zparenizor (0= myzparenizor.tostring ();
This time, myString is " -0-".
JavaScript does not has classes, but we can program as though it does.
Multiple inheritance
By manipulating a function ' s prototype object, we can implement multiple inheritance, allowing us to make a class Built from the methods of multiple classes. Promiscuous multiple inheritance can is difficult to implement and can potentially suffer from method name collisions. We could implement promiscuous multiple inheritance in JavaScript, if this example we'll use a more disciplined for M called Swiss inheritance.
Suppose there is a Numbervalue class, has a setValue method, that checks, the value is a Number in a certain range, throwing an exception if necessary. We only want it setValue and SetRange methods for our Zparenizor. We certainly don ' t want its toString method. So, we write
Zparenizor.swiss (Numbervalue, ' setValue ', ' setRange ');
This adds is only the requested methods to our class.
Parasitic inheritance
There is another-to-write Zparenizor. Instead of inheriting from Parenizor, we write a constructor that calls the Parenizor constructor, Passi ng off the result as its own. And instead of adding public methods, the constructor adds privileged methods.
function ZParenizor2 (value) { Span style= "color: #0000ff;" >var that = new Parenizor (value); that.tostring = function () {
if (
this
.getvalue ()) {
return
return " -0-" }; return that;}
Classical inheritance is about the is-a relationship, and parasitic inheritance are about the Was-a-but-now ' s A relationship. The constructor has a larger role in the construction of the object. Notice the Uber née Super method is still available to the privileged methods.
Class Augmentation
JavaScript ' s dynamism allows us to add or replace methods of a existing class. We can call the method in any time, and all present and future instances of the class would have had that metho D. We can literally extend a class at any time. Inheritance works retroactively. We Call this Class augmentation to avoid confusion with Java ' s extends, which means something else.
Object Augmentation
In the static object-oriented languages, if your want an object which be slightly different than another object, you need t o Define a new class. In JavaScript, you can add methods to individual objects without the need for additional classes. This have enormous power because you can write far fewer classes and the classes your do write can much simpler. Recall that JavaScript objects is like hashtables. You can add new values at any time. If The value is a function and then it becomes a method.
So in the example above, I didn ' t need a Zparenizor class at all. I could have simply modified my instance.
New Parenizor (0function () { if (this. GetValue ()) { Returnthis. Uber (' toString '); } return " -0-"= myparenizor.tostring ();
We added a toString method to our Myparenizor instance without using any form of inheritance. We can evolve individual instances because the language is class-free.
Sugar
The examples above work, I wrote four sugar methods. First, the method , which adds an instance method to a class.
function (Name, func) { this. Prototype[name] = func; return This ;};
This adds a public method to the Function.prototype, so all functions get it by Class augmentation. It takes a name and a function, and adds them to a function ' s prototype object.
It returns this. When I write a method, the doesn ' t need to return a value, I usually has it return this. It allows for a cascade-style of programming.
Next comes the inherits method, which indicates that one class inherits from another. It should is called after both classes is defined, but before the inheriting class ' s methods is added.
Function.method (' Inherits ',function(parent) { This. prototype =Newparent (); varD ={}, P= This. prototype; This. Prototype.constructor =parent; This. Method (' Uber ',functionUber (name) {if(! (Nameinchd) {D[name]= 0; } varF, r, T = D[name], V =Parent.prototype; if(t) { while(t) {v=V.constructor.prototype; T-= 1; } f=V[name]; } Else{f=P[name]; if(f = = This[name]) {f=V[name]; }} D[name]+ = 1; R= F.apply ( This, Array.prototype.slice.apply (arguments, [1])); D[name]-= 1; returnR; }); return This;});
Classical Inheritance in JavaScript