Use prototypes for :
- Methods
- Static properties
I use constructor for :
- Methods which can change (closure, bind etc.)
- Variable properties
It makes the code more readable, and you get more of its logic : why would you duplicate a class variable, a class constant or a method shared by all the instances ?
If it's in the prototype, it's shared by all the objects.
If it's in the constructor, it's not.
So, mostly, readability and refactorability.
All objects are linked via prototype, this is the chain
Vehicle{}
Vehicle.prototype = Vehicle; // level 1
Car = new Vehicle();
Car.prototype = Vehicle.prototype; // level 2
Engine = new Car();
Engine.prototype = Car.prototype; // level 3
Creating
When creating a new object a prototype is applied.
var a = {}; var a = function() {}; // functions also gets a proto
Inheritance of object without prototype (lightweight)
var Vehicle = { wheels: 4, automatic: true }; var Car = Object.create(Vehicle, { // creates a prototype link to Vehicle color: { enumerable: false, writable: false, configurable: false, value: "red" }, model: { value: 'Hatchback' } }); console.log(Car.wheels);// 4 console.log(Car.color); // red Car.color = 'pink'; console.log(Car.color); // red Car.wheels = 3; console.log(Car.wheels); // 3
Prototypical Inheritance (get and set)
myObject.name = 'John' // This is a set() method var name = myObject.name // This is get() method
Transversing means it will look up the tree to get() or set() a value.
var object = { a: 2 } var newObject = Object.create(object); // Inherit /* {} __proto__ a: 2 */ console.log(newObject); /* Object { a: 2 } */ newObject.name = "John"; /* name: "John" __proto__: a: 2 */ console.log(newObject); /* Result */ /* Object { a: 2, name: "John" } */ newObject.name = 'Peter'; console.log(newObject); /* Object { a: 2, name: "Peter" } */
Setting values only effects that object down (top to bottom)
var object = { a: 2 } var newObject = Object.create(object); // Inherit object.a = 3; console.log(object); // 3 newObject.a = 5; console.log(object); // 3 console.log(newObject); // 5
The "new" keyword creates the prototype
function User() { } var a = new User(); var is = Object.getPrototypeOf( a ) === User.prototype; // true console.log(is); // true
Prototype Style Example
/* User */ function User(name, age) { this.name = name; this.age = age; } User.prototype.myName = { get name() { return this._name; } } User.prototype.age = { get age() { return this._age; } } /* Student */ function Student(name, age) { User.call(this, name, age); // If we need to set anything in User for our Student when initialising } Student.prototype = Object.create(User.prototype); // important, now linked to User. /* Create a new student with prototype methods */ var newStudent = new Student('John', 22); console.log(Student.prototype.isPrototypeOf( newStudent )); // true console.log('My name is ' + newStudent.name + ' and I am ' + newStudent.age + ' years old');