In this example of prototypal inheritance, we are creating a Bug prototype. It serves as a base to provide properties and methods that all bugs share. Then we will instantiate new instances of the Bug prototype for specific implementations.
var clone = function(o) { function F(){} F.prototype = o; return new F; }; // Our insect prototype var Bug = { species: "Prototype Bug", attributes: [ 'Three Body Segments', 'Six Legs', 'Exo-Sekelton' ], getSpecies: function() { return this.species; } }; var beetle = clone(Bug); beetle.species = 'Beetle'; beetle.attributes.push('Eats Dung'); // we now have a child of the prototype with additional attributes. console.log(beetle); // The prototype var ladyBug = clone(Bug); ladyBug.species = 'Japanese Bug'; console.log(ladyBug);
The problem here is that the ladyBug object gets the attribute ‘Eats Dung’, because beetle actually modified a reference to the attributes in the prototype, not its own copy. This will trip up programmers that are used to a classical inheritance model.
The solution is to create factory functions to provide these properties and methods.
var Bug = { getSpecies: function() { return this.species; } }; Bug.species = 'default species'; Bug.addBugAttributes = function() { var attr = ['three body segments', 'six legs', 'compound eyes']; return attr; }; Bug.attributes = Bug.addBugAttributes(); var beetle = clone(Bug); beetle.species = 'Beetle'; beetle.attributes = Bug.addBugAttributes(); beetle.attributes.push('Eats Dung'); var ladyBug = clone(Bug); ladyBug.species = 'Japanese Beetle'; ladyBug.attributes = Bug.addBugAttributes(); ladyBug.attributes.push('Eats Aphids'); console.log(ladyBug); console.log(beetle);