Prototypes and Inheritance
Our base function constructor which we will be working with in this example
function Person(n,a) {
this.name = n;
this.age = a;
}
var person = new Person('Andre', 30);
*Important to know - a method is a function that is invoked(called) as a property of an object.
When a function is invoked this way, the object through which it is assesed becomes the value of the this keyword
ie: //antipattern
function say(person) {return "Hello" + name} //Hello Andre
This works but is not object-oriented. It is better to invoke a method on the object rather than passing the object to a function
ie:
var p = new Person('Andre', 30)
p.say = function() {return this.name;}
var name = p.say(); //Hello Andre
However to add a method to an object before you invoke it is silly.
ie: //improved constructor
function Person(n,a) {
this.name = n;
this.age = a;
this.say = function() {return this.name;}
}
var person = Person('Andre', 30)
person.say(); //Hello Andre
This works, but is not optimal. Every Person created will have three properties. The name and age of the Person may be different for each Person, but the say method of every singe Person object always refers to the same function.
It is inefficient to use regular properties for methods that are intended to be shared by all objects of the same class(objects created with the same constructor).
The solution is that every Javascript object has an internal reference to another object called the prototype. Any properties of the the prototype appear to be properties of an object for which it is the prototype. Our next example will clarify this.
ie.
//the constructor function initializes those properties that will be different for each instance
function Person(n,a) {
this.name = n;
this.age = a;
}
//The prototype object holds methods and other properties that should be shared by each instance
Person.prototype.say = function() {return this.name;}
A constructor gives us a name for a "class" (in this case Person is the class), of objects and initializes properties, such as name and age that may be different for each instance of the class. The prototype associated with the constructor, and each object created via the constructor inherites the same set of properties form the prototype.
It can be good to use prototype based inheritance without constructors and classes.
ie.
//Create and return an object that has p as its prototype
function inherit(p) {
function f() {} //A dummy constructor function
f.prototype = p; //Specify the prototype object we want
return new f(); //Invoke the constructor to create new object
}
*Important - Properties from the prototype are not copied form the prototype object; they only appear as if they were properties of those objects.
This is an important concept because the use of prototype can dramatically decrease the amount of memory required by each object because the object can inherit many of its properties. Also an object inherits properties even if they are added to its prototype after the object is created. This means it is possible (but not a best practice) to add new methods to existing classes. So you can alter String or Object or Array, but other programmers may not be aware of your alterations or additions and can cause bugs or problems.
To distinguish that a object has properties you can use the Object.hasOwnProperty() method
ie.
var person = new Person('Andre', 30);
person.hasOwnProperty('name'); //true: name is a direct property of person
person.hasOwnProperty('say'); //false: say is an inherited property of person
'say' in person; //true: say is a property of person
Make note that we can enumerate through the object and prototype properties are counted, but it is not the own property of the object instance.
More to come!
Feel free to ask questions, I am learning as much as you are. Take the time to test these examples via jsfiddle or jsbin or whatever IDE you use. Let me know of any errors please!