javascript inheritance
TRANSCRIPT
INHERITANCE
About Inheritance
• Code reuse is important – Inheritance can help
• JavaScript does not have classes, so no special keyword for extending
• In JS you have lot of ways to do inheritance – Classical Pa@erns – Modern Pa@erns or Prototypal Inheritance
Understanding JS Inheritance
• JS is not class based, it’s prototype-‐based! • Object inherit from another object • JS contains syntax and features that make it seem class based
Understanding Prototypes
• Prototype is an object from which other objects inherit properGes
• Any object can be a prototype • Every object has internal __proto__ property
Example var parent = {
method1: function() { print("A"); }
}
var child = {
__proto__: parent,
method2: function() { print("B"); }
}
// If method1 is not found in child, look it from
// prototype!
child.method1(); // A
child.method2(); // B
__proto__
• __proto__ is depricated and should not be used (but it works)
• To get the prototype, use – Object.getPrototypeOf(object) • It’s read only!
• How to set? – Proposal: Object.setPrototypeOf(obj, prototype)
• Not possible to change the __proto__ ..!
FuncGon Object
• When wriGng – function Animal() { }
• Lot of things happens! – Two objects created: • 1) Animal • 2) Animal.prototype
– Animal.prototype has a property constructor, that points to Animal
FuncGon Object // This is just a function. Dog is Function object! function Dog (name) { this.name = (name); } var spot = new Dog("Spot"); // true print(spot instanceof Object); // true print(Dog instanceof Function); // true print(Dog instanceof Object);
FuncGon Object function sum1(a, b) {
return a + b;
}
// =>
var sum2 = new Function("a","b", "return a+b;");
print(sum1(2,2)); // 4
print(sum2(2,2)); // 4
print(sum2.length); // number of args = 2
print(sum2.toString());
The “new” Operator
function Person() {
this.name = “Jack”;
}
// Normal function call
Person();
// Object creation
var p = new Person();
Example function Cat() { } // c.__proto__ points to Cat.prototype! var c = new Cat(); // true print(c.__proto__ === Cat.prototype); // c inherites Cat.prototype! Cat.prototype.age = 12; // 12! print(c.age);
Example function Cat() { this.name = "Jack"; } var c = new Cat(); // true print(c.__proto__ === Cat.prototype); // c inherites Cat.prototype! Let's add stuff. Cat.prototype.age = 12; Cat.prototype.saySomething = function() { print(this.name + ": hello!"); } // 12! print(c.age); // "Jack: hello!" c.saySomething();
/** PERSON **/
function Person() { }
var jack = new Person();
// jack inherites Person.prototype!
print(jack.__proto__ === Person.prototype);
Person.prototype.age = 18;
print(jack.age); // 18;
//** STUDENT **/
function Student() { }
// Let's now change the prototype of Student.
// Now Student.prototype points to Person.
var temp = new Person();
Student.prototype = temp;
var tina = new Student();
// tina inherites Student.prototype.. which is now temp!
print(tina.__proto__ === Student.prototype); // true
print(tina.__proto__ === temp); // true
// Now tina inherites Student.prototype, which is
// Person object, which inherites the Person.prototype..
print(tina.age); // 18!
Example /** Person **/ function Person() { this.name = "Jack"; } // Adding functionality to the prototype.. Person.prototype.say = function() { print(this.name + ”: hello!"); } /** Student **/ function Student() { } // Inheritance Student.prototype = new Person(); /** Test **/ var student = new Student(); student.say(); // Jack: Hello
Person.prototype
say()
new Person()
name = “Jack”
__proto__
Example /** Person **/ function Person() { this.name = "Jack"; } // Adding functionality to the prototype.. What is this?? Person.prototype.say = function() { print(this.name + ”: hello!"); } /** Student **/ function Student() { } // Inheritance Student.prototype = new Person(); /** Test **/ var student = new Student(); student.say(); // Jack: Hello
Person.prototype
say()
new Person()
name = “Jack”
__proto__
new Student()
__proto__
FuncGon Object
• Every funcGon in JS is a FuncGon object • When – var spot = new Dog(“spot”);
• Then spot’s __proto__ points to Dog.prototype!
• If a property cannot be found in an object, it is searched for in that object's prototype.
Example // here's the constructor: function Point() { } var a = new Point(); print (a.x); // undefined // set up the prototype object to have some values: Point.prototype = { x: 10, y: 20 }; // or you could do this: Point.prototype.z = 30; // make a new Point object // (a object gets an implicit reference to Point.prototype object) var a = new Point(); // Since a does not hold a property, let's look it from Point.prototype print (a.x);
Example // here's the constructor: function Point() { this.x = 10; this.y = 20; } // set up the prototype object to have some values: Point.prototype.z = 40; // make a new Point object // (a object gets an implicit reference to Point.prototype object) var a = new Point(); // Since a does not hold a property, let's look it from Point.prototype print (a.z);
//** POINT ** function Point() { } // set up the prototype object to have some values: Point.prototype = { x: 10, y: 20 }; /** PIXEL **/ function Pixel() { } Pixel.prototype = new Point(); Pixel.prototype.color = "red"; // make a new Point object // (a object gets an implicit reference to Point.prototype object) var a = new Pixel(); var b = new Pixel(); a.color = "blue"; // Since a does not hold a property, let's look it from Point.prototype print (a.color); print (b.color);
About constructors
• Prototype properGes of FuncGons have a constructor property: – var dog = new Dog(); – dog.constructor == Dog; // TRUE
• This will break when doing inheritance!
/** Person **/ function Person() { } Person.prototype.name = "Jack"; /** Student **/ function Student() { this.id = "12345"; } // Inheritance Student.prototype = new Person(); Student.prototype.id = "12345"; /** Test **/ var student = new Student(); student.age = 22; print(student.age) print(student.name); print(student.id); var person = new Person(); print(person.constructor === Person); // TRUE var student = new Student(); print(student.constructor === Student); // FALSE
/** Person **/
function Person() {
}
Person.prototype.name = "Jack";
/** Student **/
function Student() {
this.id = "12345";
}
// Inheritance
Student.prototype = new Person();
Student.prototype.id = "12345";
// FIX
Student.prototype.constructor = Student;
/** Test **/
var student = new Student();
student.age = 22;
print(student.age)
print(student.name);
print(student.id);
var person = new Person();
print(person.constructor === Person); // TRUE
var student = new Student();
print(student.constructor === Student); // FALSE
Inheritance: Prototypal
• In EcmaScript 5 a protypal inheritance pa@ern is part of the language – Object.create() – var child = Object.create(parent);
• The create-‐funcGon function create(o) { function F() {} f.prototype = o; return new F();
}
Example function Point(x,y) { this.x = x; this.y = y; } var pixel = Object.create(new Point(12,0)); pixel.color = "red"; print(pixel.x); print(pixel.color);