Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Jessica Barnett
Jessica Barnett
8,028 Points

Adding methods to Javascript Prototypes

I was doing a little exercise to practice with javascript prototypes, and ran into a snag.

var frog = new Animal("frog", "pond", 3);

frog.printAnimal(); //this works
frog.grow(4); //but this function is coming up as undefined...?

function Animal (species, habitat, age){
    this.species = species;
    this.habitat = habitat;
    this.age = age;
    //first method uses this.methodName
    this.printAnimal = function(){
        return age + " year old " + species + "who lives in the " + habitat + ".";
    }
}

//second method uses constructor.prototype.methodName
Animal.prototype.grow = function(yearsOlder) {
    this.age += yearsOlder;
};

Basically, I added two methods to the Animal prototype, one using this.methodName in the constructor function, and the other outside the constructor using constructor.prototype.methodName

I'm pretty sure both are supposed to work, but when my code hits the second one, the console says it's undefined. Does anyone know why that might be?

3 Answers

If you're still interested in why this is happening...

Adding a method to a prototype means you are declaring a function. It's just that the variable that points at that function is a property on a prototype.

In JavaScript, you can declare functions in two ways:

var myFunction = function() {
   return 1;
}

// or

function myOtherFunction () {
   return 1;
}

The first one looks like any other value assignment, only the value being assigned is a function. As such, it's hoisted, or rather the variable declaration part is.

When the JavaScript compiler hits the myFunction function, it will hoist the variable declaration (var myFunction) to the top of the scope, but it will keep the value assignment for the engine when the script is run. Because of that you cannot make calls to myFunction() above its definition. It will be undefined until the definition is run.

myOtherFunction() uses the function keyword. This function declaration is handled by the compiler during parse-time. You can think of the whole function declaration/definition getting hoisted to the top of the scope so it's available at run-time.

Now, if you look at the method definition, it looks like the first scenario (myFunction()) without the var keyword. But you don't need it as you're defining a property on an existing object (function). It won't get hoisted and that part of the code needs to be executed before you use it.

Note that you can call your constructor before it appears in the code. That's because it's using the function keyword for declaration/definition like the second scenario (myOtherFunction()).

Animal.prototype.printAnimal is a part of the constructor (declared as this.printAnimal) so it's available as soon as the constructor is called. That's why you can call it as well, before it appears in the code.

Finally, for the sake of clarity and code readability, even if you can call something before it appears in the code, it doesn't mean you should. Always put the constructors and methods to the top of your code to avoid confusion and unwanted errors.

Jessica Barnett
Jessica Barnett
8,028 Points

Totally just answered my own question! For anyone who's interested, if you add methods the 2nd way, any calls to that method have to be further down in the document. So I just had to move frog.grow() to the bottom.

It's always right after I ask for help that I figure it out!
thanks!

Jessica Barnett
Jessica Barnett
8,028 Points

Hoisting. That is definitely something that would've tripped me up over an over if someone hadn't pointed it out. Thank you very much for this very clear answer!

Found this article helpful too: Answering Baranovskiy’s JavaScript quiz