Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good Example of JavaScript's Prototype-Based Inheritance

I have been programming with OOP languages for over 10 years but I'm learning JavaScript now and it's the first time I've encountered prototype-based inheritance. I tend to learn fastest by studying good code. What's a well-written example of a JavaScript application (or library) that properly uses prototypal inheritance? And can you describe (briefly) how/where prototypal inheritance is used, so I know where to start reading?

like image 689
Alex Reisner Avatar asked Jan 14 '10 14:01

Alex Reisner


People also ask

What is prototypal inheritance give example?

Nowadays, in modern language, it is being set using __proto__. Example In the given example, there are two objects 'person' and 'GFGuser'. The object 'GFGuser' inherits the methods and properties of the object 'person' and further uses them.

How do you use prototype inheritance?

When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.

What is prototype prototype chain prototype inheritance?

That prototype object has its own prototype, and so on until an object whose prototype is null is reached. By definition, null has no prototype, and acts as the final link in this chain of prototypes. This is known as prototypical inheritance and differs from class inheritance.

How is JavaScript's prototype inheritance different from traditional class based inheritance?

The most important difference between class- and prototype-based inheritance is that a class defines a type which can be instantiated at runtime, whereas a prototype is itself an object instance.


2 Answers

As mentioned, the movies by Douglas Crockford give a good explanation about the why and it covers the how. But to put it in a couple of lines of JavaScript:

// Declaring our Animal object var Animal = function () {      this.name = 'unknown';      this.getName = function () {         return this.name;     }      return this; };  // Declaring our Dog object var Dog = function () {      // A private variable here             var private = 42;      // overriding the name     this.name = "Bello";      // Implementing ".bark()"     this.bark = function () {         return 'MEOW';     }        return this; };   // Dog extends animal Dog.prototype = new Animal();  // -- Done declaring --  // Creating an instance of Dog. var dog = new Dog();  // Proving our case console.log(     "Is dog an instance of Dog? ", dog instanceof Dog, "\n",     "Is dog an instance of Animal? ", dog instanceof Animal, "\n",     dog.bark() +"\n", // Should be: "MEOW"     dog.getName() +"\n", // Should be: "Bello"     dog.private +"\n" // Should be: 'undefined' ); 

The problem with this approach however, is that it will re-create the object every time you create one. Another approach is to declare your objects on the prototype stack, like so:

// Defining test one, prototypal var testOne = function () {}; testOne.prototype = (function () {     var me = {}, privateVariable = 42;     me.someMethod = function () {         return privateVariable;     };      me.publicVariable = "foo bar";     me.anotherMethod = function () {         return this.publicVariable;     };      return me;  }());   // Defining test two, function var testTwo = ​function() {     var me = {}, privateVariable = 42;     me.someMethod = function () {         return privateVariable;     };      me.publicVariable = "foo bar";     me.anotherMethod = function () {         return this.publicVariable;     };      return me; };   // Proving that both techniques are functionally identical var resultTestOne = new testOne(),     resultTestTwo = new testTwo();  console.log(     resultTestOne.someMethod(), // Should print 42     resultTestOne.publicVariable // Should print "foo bar" );  console.log(     resultTestTwo.someMethod(), // Should print 42     resultTestTwo.publicVariable // Should print "foo bar" );    // Performance benchmark start var stop, start, loopCount = 1000000;  // Running testOne start = (new Date()).getTime();  for (var i = loopCount; i>0; i--) {     new testOne(); } stop = (new Date()).getTime();  console.log('Test one took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');    // Running testTwo start = (new Date()).getTime();  for (var i = loopCount; i>0; i--) {     new testTwo(); } stop = (new Date()).getTime();  console.log('Test two took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds'); 

There is a slight downside when it comes to introspection. Dumping testOne, will result in less useful information. Also the private property "privateVariable" in "testOne" is shared in all instances, als helpfully mentioned in the replies by shesek.

like image 67
Dynom Avatar answered Oct 13 '22 04:10

Dynom


Douglas Crockford has a nice page on JavaScript Prototypal Inheritance:

Five years ago I wrote Classical Inheritance in JavaScript. It showed that JavaScript is a class-free, prototypal language, and that it has sufficient expressive power to simulate a classical system. My programming style has evolved since then, as any good programmer's should. I have learned to fully embrace prototypalism, and have liberated myself from the confines of the classical model.

Dean Edward's Base.js, Mootools's Class or John Resig's Simple Inheritance works are ways to do classical inheritance in JavaScript.

like image 39
Gregory Pakosz Avatar answered Oct 13 '22 06:10

Gregory Pakosz