-
Notifications
You must be signed in to change notification settings - Fork 3
Inheritance
PhoenixAndMachine edited this page Apr 7, 2014
·
2 revisions
There are three ways to achieve inheritance in Javascript. The key is to play with prototype. Before reading these code, it is better for you to understand prototype chain in JS, and the differences between prototype and __proto__.
/* Extend function */
function extend(subClass, superClass) {
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superclass = superClass.prototype;
if(superClass.prototype.constructor==Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
}
/* Person */
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.getAge = function() {
return this.age;
}
/* Author */
function Author(name, age, books) {
Author.superclass.constructor.call(this, name, age);
this.books = books;
}
extend(Author, Person);
Author.prototype.getBooks = function() {
return this.books;
}
Author.prototype.getName = function() {
var name = Author.superclass.getName.call(this); // be able to call methods of superclass
return name + ', Author of ' + this.getBooks().join(', ');
}
/* Usage */
var bart = new Author('Bart Van lierde', 38, ['Zot van A']);
console.log("----------------bart can call its own properties--------------");
console.log(Object.getOwnPropertyNames(bart)); // [ 'books', 'name', 'age' ]
console.log("----------------bart is an instance of Author-----------------");
console.log(bart instanceof Author); // true
console.log(bart.__proto__===Author.prototype); // true
console.log("----------------bart can call Author's methods(improved)----------------");
console.log(Author.prototype);
/*
Output
{
constructor: { [Function: Author] superclass: { getName: [Function], getAge: [Function] } },
getBooks: [Function],
getName: [Function] // overwritten in Author.prototype.getName
}
*/
console.log("----------------bart is an instance of Person-----------------");
console.log(bart instanceof Person); // true
console.log("----------------bart can call Person's methods--------------");
console.log(bart.__proto__.__proto__); // { getName: [Function], getAge: [Function] }
console.log(bart.getName());
/* Clone function */
function clone(object) {
function F() {}
F.prototype = object;
return new F;
}
/* Composite Object */
var configuration = {
name: 'default name',
}
configuration.display = function() {
console.log("Name: " + this.name);
console.log("limit_package: " + this.details.limit_package);
console.log("bandwidth: " + this.details.bandwidth);
}
/* method for creating child object */
configuration.createDetails = function() {
return {
limit_package: 'default limit package',
bandwidth: 'default bandwidth'
}
}
configuration.details = configuration.createDetails();
var cf1 = clone(configuration);
var cf2 = clone(configuration);
cf1.details = configuration.createDetails();
cf1.details.bandwidth = 'cf1 bandwidth';
console.log("---------configuration---------");
configuration.display();
console.log("--------------cf1--------------");
cf1.display();
console.log("--------------cf2--------------");
cf2.display();
/* Mixin Class */
var Mixin = function() {};
Mixin.prototype = {
serialize: function() {
var output = [];
for(key in this) {
output.push(key + ':' + this[key]);
}
return output.join(', \n');
},
useless: function() {
console.log("USELESS FUNCTION");
}
}
/* Augment function with improvement */
function augment(receivingClass, givingClass) {
if(arguments[2]) {
for (var i=2, length=arguments.length; i<length; i++) {
if(!receivingClass.prototype[arguments[i]]) {
receivingClass.prototype[arguments[i]] =givingClass.prototype[arguments[i]];
}
};
}
else {
for(methodName in givingClass.prototype) {
if(!receivingClass.prototype[methodName]) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
}
}
}
/* Usage */
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.getAge = function() {
return this.age;
}
augment(Person, Mixin, 'serialize');
var p = new Person('Einstein', 38);
console.log(p.serialize());