There's a principle in programming called Don't Repeat Yourself (DRY). The reason repeated code is a problem is because any change requires fixing code in multiple places. This usually means more work for programmers and more room for errors.
Notice in the example below that the
eatmethod is shared byCatandBear:
function Cat(name) {
this.name = name;
}
Cat.prototype = {
constructor: Cat,
eat: function() {
console.log("nom nom nom");
}
};
function Bear(name) {
this.name = name;
}
Bear.prototype = {
constructor: Bear,
eat: function() {
console.log("nom nom nom");
}
};
- The
eatmethod is repeated in two places. The code can be edited to follow the DRY principle by creating asupertype(or parent) calledAnimal:
function Animal() { }
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
- Since
Animalincludes theeatmethod, you can remove it fromCatandBear:
function Cat(name) {
this.name = name;
}
Cat.prototype = {
constructor: Cat
};
function Bear(name) {
this.name = name;
}
Bear.prototype = {
constructor: Bear
};
function Animal() { }
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
- We just edited the code in the spirit of DRY by moving the
eatmethod to theAnimalsupertype.
Inherit Behaviors from a Supertype
- In the previous post, we created a
supertypecalledAnimalthat defined behaviors shared by all animals:
function Animal() { }
Animal.prototype.eat = function() {
console.log("nom nom nom");
};
- This and the next part will cover how to reuse
Animal'smethods insideDogwithout defining them again. It uses a technique called inheritance. This challenge covers the first step: make an instance of thesupertype(or parent).
let animal = Object.create(Animal.prototype);
- You could also use this,
let animal = new Animal();
but there are some disadvantages when using this syntax for inheritance, which are too complex for the scope of this example.
Object.create(obj)creates a new object, and setsobjas the new object'sprototype. Recall that theprototypeis like the "recipe" for creating an object. By setting theprototypeofanimalto beAnimal'sprototype, you are effectively giving theanimalinstance the same "recipe" as any other instance ofAnimal.
function Animal() { }
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
let beagle = Object.create(Animal.prototype)
beagle.eat(); // will display nom nom nom
console.log(beagle instanceof Animal); // will display true
Setting the Child's Prototype to an Instance of the Parent
In the previous section you saw the first step for inheriting behavior from the
supertype(or parent)Animal: making a new instance ofAnimal.This post covers the next step: set the
prototypeof thesubtype(or child)—in this case,Dog—to be an instance ofAnimal.
Dog.prototype = Object.create(Animal.prototype);
- Remember that the
prototypeis like the "recipe" for creating an object. In a way, the recipe forDognow includes all the key "ingredients" fromAnimal.
function Animal() { }
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
function Dog() { }
Dog.prototype = Object.create(Animal.prototype); // <----
let beagle = new Dog();
beagle.eat(); // will display when console.log nom nom nom
-
beagleinherits all ofAnimal'sproperties, including theeatmethod.
Resetting an Inherited Constructor Property
When an object inherits its
prototypefrom another object, it also inherits the supertype's constructor property.Here's an example:
function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
let beagle = new Dog();
beagle.constructor
- But
beagleand all instances ofDogshould show that they were constructed byDogand notAnimal. To do so, you can manually setDog'sconstructor property to the Dog object:
function Animal() { }
function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
let beagle = new Dog();
console.log(beagle.constructor); // will display [Function: Dog]
Add Methods After Inheritance
- A constructor function that inherits its
prototypeobject from asupertypeconstructor function can still have its own methods in addition to inherited methods. - For example,
Dogis a constructor that inherits itsprototypefrom Animal:
function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };
function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
- In addition to what is inherited from
Animal, you want to add behavior that is unique toDogobjects. Here,Dogwill get abark()function. Functions are added toDog'sprototypethe same way as any constructor function:
Dog.prototype.bark = function() {
console.log("Woof!")
};
- Now instances of
Dogwill have botheat()andbark()methods.
function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };
function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() { // <----
console.log("Woof!")
}
let beagle = new Dog();
beagle.eat();
beagle.bark()
-
beagle.eat()would display the stringnom nom nomin the console, andbeagle.bark()would display the stringWoof!.
Top comments (4)
Next up:
Using composition so you don't use inheritance:DOf course haha as I’m going I’m learning
^ this!
I warmly recommend to read this article where Matthias Verraes explains that DRY is not about code but knowledge:
verraes.net/2014/08/dry-is-about-k...
Cheers