14 - Prototype to the Rescue - Why use a prototype here?


#1

Hey guys, this is how Codecademy teaches us to use a prototype to add a function to a class:

function Dog (breed) {
this.breed = breed;
};

// here we make buddy and teach him how to bark
var buddy = new Dog("golden Retriever");
Dog.prototype.bark = function() {
console.log("Woof");
};
buddy.bark();

// here we make snoopy
var snoopy = new Dog("Beagle");
/// this time it works!
snoopy.bark();

In a previous level, in order to get Snoopy to bark I just added a function to the constructor:

function Dog (breed) {
this.breed = breed;
this.bark = function() {
console.log("Bark!");
}
};

It seems like adding the function to the constructor is more straightforward, but if Codecademy is teaching us to add the function later by targeting the prototype, there must be an advantage to that method. Can anyone please explain why that would be desirable over adding the function in the constructor? Thanks!


#2

Follow-up question! In the description, Codecademy makes this comment:

In general, if you want to add a method to a class such that all members
of the class can use it, we use the following syntax to extend the prototype:

But when I change the order of the code so that snoopy.bark is called before the prototype extension, I get an error message.

function Dog (breed) {
this.breed = breed;
};

// here we make snoopy
var snoopy = new Dog("Beagle");
/// this time it works!
snoopy.bark();

// here we make buddy and teach him how to bark
var buddy = new Dog("golden Retriever");
Dog.prototype.bark = function() {
console.log("Woof");
};
buddy.bark();

So the prototype extension does retroactively affect existing members of a class, but it doesn't retroactively apply to a function called before the extension was made. Am I understanding that correctly?

And did I even explain my question coherently? :sweat_smile:


#3

Hi Kat!

There are slight but important differences to the ways that methods and properties are treated when using the constructor vs the prototype methods.

The constructor

function Dog (breed) {
    this.breed = breed;
    this.bark = function() {
        console.log("Woof");
    }
};

In this example, when you create a new Dog object it has its own copy of the bark() function. If you had 1000 Dog objects, you'd have 1000 bark() functions (albeit all of them doing the same thing).

The benefit of this method is that you might want to write a function which has access to private data contained in the constructor.

The prototype

function Dog (breed) {
    this.breed = breed;
};
    
Dog.prototype.bark = function() {
    console.log("Woof");
};

In this version, the bark() function has been added to the Dog object's prototype property. The prototype property is itself an object which contains every method and property to be inherited for the object in question. So this means that if you have 1000 Dog objects, they all have access to one single bark() function located in the prototype.

The benefits of this method is that you can not only retroactively define methods and properties, but that you require less memory to do so.

So in your second example, you should be able to call snoopy.bark() as long as you do so after defining Dog.prototype.bark.

Hope this helps!


#4

Ahh, that makes sense. I can imagine that efficiency would be really important when working with a lot of code. Thanks so much for your explanation!