Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prototypal inheritance concept in javascript as a prototype based language

You know Javascript is a prototype-based programming language .
I have read some books about Javascript and its prototypal inheritance concept but:

"If you can't explain it to a six-year old, you really don't understand it yourself.”. Well, I tried to explain JavaScript prototype concept to a 22-year old friend and completely failed!

How would you explain it to a 6-year old person that is strangely interested in that subject?
I have seen some examples given in Stack Overflow, and it did not help.

like image 640
Dariush Jafari Avatar asked Aug 30 '12 16:08

Dariush Jafari


People also ask

What is prototype and prototypal inheritance in JavaScript?

In JavaScript, an object can inherit properties of another object. The object from where the properties are inherited is called the prototype. In short, objects can inherit properties from other objects — the prototypes.

What is prototypal inheritance give example?

In programming, we often want to take something and extend it. For instance, we have a user object with its properties and methods, and want to make admin and guest as slightly modified variants of it.

What is prototype explain how inheritance works in JavaScript?

Simply put, prototypical inheritance refers to the ability to access object properties from another object. We use a JavaScript prototype to add new properties and methods to an existing object constructor. We can then essentially tell our JS code to inherit properties from a prototype.

Is JavaScript prototype like 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.


3 Answers

Classical inheritance is about extending types of things. Say you have a class, like Bike. When you want extend the behaviour, you have to design a new type of bike (like MotorBike).

It's like building a factory - you make lots of blueprints, and blueprints that reference those blueprints, but in order to ride one you have to take the blueprint and make something from it.

Prototype-based inheritance is about extending things themselves. Say you have a way of making Bike objects. You take one of these Bikes into your garage, and you strap a jet engine to it.

This is not according to the blueprint. This is something you've done to this particular bike. But your friends see your contraption and want one too. So instead of making a blueprint for your new design, you stick up a sign saying "JetBike factory" and just start making more of them. And every time you can't remember how something fits together, instead of looking at a blueprint you just look at your original bike. Your original bike is the prototype bike, and all the new bikes are based on it.

Now, for a genuine 6-year-old, that's probably where I'd stop (if I hadn't lost them already), but in reality prototype-based inheritance doesn't just construct copies, it does something even cooler - it actually links the new JetBike objects to the original prototype bike you have in your garage. If you replace the suspension on your prototype bike, then all your friends' bikes will also magically have their suspension replaced as well.

Let's look at some JS-ish pseudo-code:

function Bike() {
    this.wheels = 2;
}
Bike.prototype = {
    ride: function() {
        // Ride the bike
    },
    crash: function() {
        // Fall off the bike
    }
};

function JetBike() {
    this.engines = 2;
}
// Start with an ordinary bike
JetBike.prototype = new Bike();
// Modify it
JetBike.prototype.fly = function () {
    // Engage thrusters and head for the ramp
};
like image 122
cloudfeet Avatar answered Oct 21 '22 20:10

cloudfeet


Javascript is an object oriented language that is unique in that it does not have classes. Instead we use functions to create objects.

All functions have a prototype, which all objects you create using that function will inherit all properties and methods from. Since Javscript does not have classes, you perform inheritance using an actual object to inherit from (as opposed to a class). You can set a function's prototype to an object, allowing all objects you create with that function to inherit all the methods and properties of the function's prototype object.

So if I have a function that creates an object:

function Foo() {

}
Foo.prototype.someProperty = 'blahblahblah';

You can create another function that creates an object, and allow it to inherit an objects properties and methods by setting the functions prototype to that object.

function Bar() {

}
Bar.prototype = new Foo();

Then you can access all the stuff that was inherited.

var bar = new Bar();
alert( bar.someProperty ); // blahblahblah
like image 25
dqhendricks Avatar answered Oct 21 '22 20:10

dqhendricks


Unlike most other object-oriented languages, JavaScript doesn’t actually have a concept of classes. In most other object-oriented languages you would instantiate an instance of a particular class, but that is not the case in JavaScript.
In JavaScript, objects can create new objects, and objects can inherit from other objects.
This whole concept is called prototypal inheritance.

but how we can make an object?
Simply you can create a generic object with {}.

var a = {};
a.prop = "myprop";
console.log(a); //Object { prop="myprop" }

you cannot create instance of a because it is not a function. in other words it has not special internal method [[Construct]].

In JavaScript any function can also be instantiated as an object. The function below is a simple function which takes a name and saves it to the current context:

function User( name ) {
   this.name = name;
}

We can see that User is instance of Function:

alert(User instanceof Function); //true

Create a new instance of that function, with the specified name:

var me = new User( "My Name" ); 

We can see that its name has been set as a property of itself:

alert( me.name == "My Name" ); //true

And that it is an instance of the User object:

alert( me.constructor == User ); //true

Now, since User() is just a function, what happens when we treat it as such?

User( "Test" );

Since its this context wasn't set, it defaults to the global window object, meaning that window.name is equal to the name provided:

alert( window.name == "Test" ); //true

The constructor property exists on every object and will always point back to the function that created it. This way, you should be able to effectively duplicate the object, creating a new one of the same base class but not with the same properties. An example of this can be seen below:

var you = new me.constructor();

We can see that the constructors are, in fact, the same:

alert( me.constructor == you.constructor ); //true

Prototype And Public Methods

Prototype simply contains an object that will act as a base reference for all new copies of its parent object. Essentially, any property of the prototype will be available on every instance of that object. This creation/reference process gives us a cheap version of inheritance.
Since an object prototype is just an object, you can attach new properties to them, just like any other object. Attaching new properties to a prototype will make them a part of every object instantiated from the original prototype, effectively making all the properties public. example:

function User( name, age ){
   this.name = name;
   this.age = age;
}

Adding methods and properties to the prototype property of the constructor function is another way to add functionality to the objects this constructor produces. Let's add one more property, CardNo and a getName() method:

User.prototype.CardNo='12345';
User.prototype.getName = function(){
  return this.name;
};

And add another function to the prototype. Notice that the context is going to be within the instantiated object.

User.prototype.getAge = function(){
   return this.age;
};

Instantiate a new User object:

var user = new User( "Bob", 44 );

We can see that the two methods we attached are with the object, with proper contexts:

alert( user.getName() == "Bob" ); //true
alert( user.getAge() == 44 ); //true

So every function in javascript has a prototype property. Its initial value is an empty object ({}). Notice that generic objects (not functions) don't have the prototype property:

alert( user.prototype ); //undefined (and it is not useful even you define it)

Delegation

When you try to access a property of user, say user.name the JavaScript engine will look through all of the properties of the object searching for one called name and, if it finds it, will return its value:

alert( user.name );

What if the javascript engine cannot find the property? It will identify the prototype of the constructor function used to create this object (same as if you do user.constructor.prototype). If the property is found in the prototype, this property is used:

alert(user.CardNo); // "12345"

and so...
If you want to distinguish between the object's own properties versus the prototype's properties, use hasOwnProperty(). Try:

alert( user.hasOwnProperty('name') ); //true
alert( user.hasOwnProperty('CardNo') ); //false

Private Methods

When you directly set a property for a function, it will be private. example:

function User()
{
    var prop="myprop";
    function disp(){
       alert("this is a private function!");
    }
}
var we = new User();
alert(we.prop); //undefined
we.disp(); // Fails, as disp is not a public property of the object

Privileged Methods

Privileged methods is a term coined by Douglas Crockford to refer to methods that are able to view and manipulate private variables (within an object) while still being accessible to users as a public method. example:
Create a new User object constructor:

function User( name, age ) {
   //Attempt to figure out the year that the user was born:
   var year = (new Date()).getFullYear() – age;

   //Create a new Privileged method that has access to the year variable, but is still publically available:
   this.getYearBorn = function(){
      return year;
   };
}

Create a new instance of the user object:

var user = new User( "Bob", 44 );

Verify that the year returned is correct:

alert( user.getYearBorn() == 1962 ); //true

And notice that we're not able to access the private year property of the object:

alert( user.year == null ); //true

In essence, privileged methods are dynamically generated methods, because they’re added to the object at runtime, rather than when the code is first compiled. While this technique is computationally more expensive than binding a simple method to the object prototype, it is also much more powerful and flexible.

Static Methods

The premise behind static methods is virtually identical to that of any other normal function. The primary difference, however, is that the functions exist as static properties of an object. As a property, they are not accessible within the context of an instance of that object; they are only available in the same context as the main object itself. For those familiar with traditional classlike inheritance, this is sort of like a static class method.
In reality, the only advantage to writing code this way is to keep object namespaces clean.
A static method attached to the User object:

function User(){}
User.cloneUser = function( user ) {
   //Create, and return, a new user
   return new User( user.getName(), user.getAge() );
};

The cloneUser function is only accessible by User:

var me = new User();
me.cloneUser(me); //Uncaught TypeError: Object #<User> has no method 'cloneUser' 
like image 38
2 revs Avatar answered Oct 21 '22 19:10

2 revs