cat = new Animal(); cat instanceof Animal; // true Forces use of a Constructor Uses the "new" keyword "instanceof" works Utilizes all the language features provided for inheritance
Ctor var Animal = function() {}; var Cat = function() { Animal.call(this); }; util.inherits(Cat, Animal); Node.js Provides helpers built in the language
language All Objects have a prototype Everything in JS is an Object The Prototype is the blueprint for creating objects and instances The Instances or Objects do not have a prototype Functions have a prototype var str = new String(); var bool = new Boolean(); var num = new Number();
blueprint for creating objects and instances var Animal = function(name) { this.name = name; }; Animal.prototype.getName = function() { return this.name; }; var pony = new Animal('pony'); pony.getName(); // "pony" The instance Invokes the Constructor The Constructor Instance local variable A method
hole... var fn = function() {} fn.prototype // fn {} // -> constructor: function() // -> __proto__: Object All prototypes have at least two properties: constructor: A Function that gets invoked when constructing the instance __proto__: A reference to the parent prototype
hole... var str = 'a string'; str.__proto__; // Outputs the Object that was used to construct // the "str" instance: // String {length: 0, [[PrimitiveValue]]: ""} All variables of any type in Javascript have the __proto__ property!
type in Javascript have the __proto__ property! Remember! Remember! __proto__ is a reference Points to the Object that constructed the instance Instances using the "new" keyword have a __proto__ that points to the Ctor
ParentCtor) { function TempCtor() {}; TempCtor.prototype = ParentCtor.prototype; ChildCtor.prototype = new TempCtor(); }; ChildCtor.prototype.constructor = ChildCtor; Create a temporary Constructor to copy the Parent Prototype on.
ParentCtor) { function TempCtor() {}; TempCtor.prototype = ParentCtor.prototype; ChildCtor.prototype = new TempCtor(); }; ChildCtor.prototype.constructor = ChildCtor; Copy the Parent's Prototype to the temporary Constructor's prototype
ParentCtor) { function TempCtor() {}; TempCtor.prototype = ParentCtor.prototype; ChildCtor.prototype = new TempCtor(); }; ChildCtor.prototype.constructor = ChildCtor; Instanciate the temporary Ctor and assign it by overwriting the Child's prototype. This is where inheritance happens.
ParentCtor) { function TempCtor() {}; TempCtor.prototype = ParentCtor.prototype; ChildCtor.prototype = new TempCtor(); }; ChildCtor.prototype.constructor = ChildCtor; Let's break this out, too much happened here: "var inst = new TempCtor()" we created an instance The instance has a __proto__ referencing the TempCtor Which in our case is the Parent's Prototype.
ParentCtor) { function TempCtor() {}; TempCtor.prototype = ParentCtor.prototype; ChildCtor.prototype = new TempCtor(); }; ChildCtor.prototype.constructor = ChildCtor; We overwrite the prototype's special property "constructor" Using the actual Child Ctor Remember, the Ctor is a function
ParentCtor) { function TempCtor() {}; TempCtor.prototype = ParentCtor.prototype; ChildCtor.prototype = new TempCtor(); }; ChildCtor.prototype.constructor = ChildCtor; So essentially we discard the default Child's prototype Overwriting it with the instance of the Parent Ctor
functions are accessible, and in what context it is being executed. In the case of an Instance, scope is critical in maintaining access to methods and local properties
{ this.name = name; // this will fail this.on('some event', this.doSomething); // this is ok this.on('some event', this.doSomething.bind(this)); }; var animal = new Animal('cat'); // this will fail $('body').on('load', animal.onLoad); // this is ok $('body').on('load', animal.onLoad.bind(animal));
= function(name, color) { Animal.call(this, name); this.color = color; }; util.inherits(Cat, Animal); Cat.prototype.getColor = function() { return this.color; }; 1. First thing you do in your Ctor is to call your Parent's Ctor using your own, new, context (scope) 2. Then, right after the Ctor, invoke the inherits function 3. Afterwards we define our own methods and can even overwrite the parent's 1 3 2
a Ctor creating childs the longer the chain gets Js will lookup serially for a method all the way up to the last prototype This can result in performance hits in some particular cases
Everything else on the Ctor var Animal = function(name) { this.name = name; }; // Never do this Animal.prototype.name = ''; Animal.prototype.getName = function() { return this.name; }; var cat = new Animal('cat'); var dog = new Animal('dog'); cat.getName(); // "dog"
Constructors "Constructors" and not "Classes" because they do not behave like Classes They resemble a Class, thus the term "Classical Inheritance" But in reality, this is "Prototypical Inheritance" We signify a Ctor by capitalizing the first letter var Animal = function() {}
constructor strictly to construct the instance Asynchronous operations are forbidden! Define any and all properties in the constructor Use null to initialize properties with no value Never return any value from the Ctor It will screw up everything var Animal = function() { this.name = null; this.color = null; }
define a method on the Ctor directly, that is considered a Static function and will not be inherited var Animal = function() { this.name = null; this.color = null; } Animal.staticFn = function() { // Will not be inherited };