JavaScript Object Constructors & Prototypes
up:: JS Objects
Basic syntax
function Bird() {
this.name = "Albert";
this.color = "blue";
this.numLegs = 2;
}
let parrot = new Bird();
Best practise
Objects are written in title case to distinguish from functions.
Terminology
The created object from a constructor is called an instance. For example, in the code above,
parrot
is the instance.
Prototypes
All objects in JS (with some exceptions) have a prototype. Because prototype is an object, it itself can have a prototype!
function Bird(name) {
this.name = name;
}
typeof Bird.prototype;
let duck = new Bird("Donald");
This evaluates to Object.prototype
.
It’s great because of prototype chaining, we can access all of the Object’s prototype functions from the Bird
object. That’s where .hasOwnProperty()
comes from! Not being able to access that implemented method is an example of Abstraction.
Here is the chain:
Bird
is the supertype forduck
.duck
is the subtype ofBird
Object
is the supertype forBird
andduck
, and all objects in JavaScript.
This is the basics of Inheritance.
Setting child prototypes
This can also be used for Don’t repeat yourself purposes: If Bird
and Dog
each have the same function of eat()
in their properties, move it to an Animal
supertype.
Then, you can create a subclass with all of the properties (the prototype
) of the superclass:
Bird.prototype = Object.create(Animal.prototype);
// Created elements inherit the constructor from superclass
let duck = new Bird();
duck.constructor // => Animal
// That often isn't what we want. So make sure to set the constructor explicitly.
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;
Mixins
For unrelated shared functions, mixins are more appropriate than inheritance.
let flyMixin = function(obj) {
obj.fly = function() {
console.log("Flying, wooosh!");
}
};
let bird = {
name: "Donald",
numLegs: 2
};
let plane = {
model: "777",
numPassengers: 524
};
flyMixin(bird);
flyMixin(plane);
flyMixin
add the fly()
function to the object passed in.
Closure
All of the code being able to access properties of an object can be dangerous. Think about passwords or bank account being able to be modified from anywhere in a codebase.
By defining a variable inside the function, it can’t be modified. This is the basic principle of Encapsulation.
function Bird() {
let hatchedEgg = 10;
this.getHatchedEggCount = function() {
return hatchedEgg;
};
}
let ducky = new Bird();
ducky.getHatchedEggCount();
Modules
We can use immediately invoked function expressions (IIFE) to group multiple functions to add on objects. See below:
let motionModule = (function () {
return {
glideMixin: function(obj) {
obj.glide = function() {
console.log("Gliding on the water");
};
},
flyMixin: function(obj) {
obj.fly = function() {
console.log("Flying, wooosh!");
};
}
}
})();
motionModule.glideMixin(duck);
duck.glide();