Function coming back undefined?

Hey guys I’m trying to debug and test this program as I write it, and for some reason my purchase() function keeps coming back undefined. Here is the code…

// Create a constructor for Album object
function Album(title, artist, price){
    this.title = title;
    this.artist = artist;
    this.price = price;
    this.date = new Date();
    this.quantity = Math.floor((Math.random() * 10) + 1);
    function purchase(){
        this.quantity--;
        if (this.quantity > 0){
            return 1;
        }
        else{
            return -1;
        }
    };
};
// Create classes that inherit from Album
var pimpAButterfly = new Album("To Pimp a Butterfly", "Kendrick Lamar", 19.99);
pimpAButterfly.tracklisting = ["Wesleys Theory", "For Free", "King Kunta", "Institutionalized", "These Walls"];

var blameItAll = new Album("Blame It All On My Roots", "Garth Brooks", 29.98);
blameItAll.tracklisting = ["Blame It All On My Roots", "Neon Moon", "Papa", "Thunder Rolls"];

var killLights = new Album("Kill the Lights", "Luke Bryan", 10.83);
killLights.tracklisting = ["Kick the Dust Up", "Kill the Lights", "Strip it Down", "Home Alone Tonight"];

var platinum = new Album("Platinum", "Miranda Lambert", 10.61);
platinum.tracklisting = ["Girls", "Platinum", "Little Red Wagon", "Priscilla", "Automatic"];

var painKiller = new Album("PainKiller", "Little Big Town", 10.61);
painKiller.tracklisting = ["Quit Breaking Up With Me", "Day Drinking", "Tumble and Fall", "Painkiller"];

// Store these classes in an array
var albums = [pimpAButterfly, blameItAll, killLights, platinum, painKiller];
console.log(blameItAll.quantity);
console.log(blameItAll.purchase());
console.log(blameItAll.quantity);

My three console.log statements are to check to see if the quantity is actually be deducted by one. When I run the program; I keep getting an error saying that purchase() is undefined and is not a function. Any help would be appreciated. Thank you.

Hi Jason,

The problem here is that the way you’ve declared the function purchase means that it’s only available within the scope of the constructor. To make it public, you need to declare it like this:

this.purchase = function() {
    // ...
}

@fretburner Thank you for your help. I solved it by taking the function out of the constructor and then
stating Album.prototype.purchase = function(){
With my block of code
};
That seemed to work. Should I just put the function back in my constructor or keep it out. Which is cleaner?

Yeah adding the method to the prototype can be a good idea, as it saves memory. Each instance of Person will then share the method, instead of having their own copy.

I dont understand the difference between adding the method to the prototype and just incorporating it into the constructor. Isn’t the constructor essentially already the prototype for my class?

Not really because they have a completely different effect on the memory usage which might not seem like a huge deal, but it can have a big difference on performance over the long haul.

I don’t typically like to refer people to other sites, but this does a REAL nice job of explaining the difference between the two.

I was part-way through typing my reply when I saw that Dave has linked you to an explanation, which is probably going to explain things better than I could. Feel free to come back with any questions you might have though, and we could go over some examples to clarify any concepts you’re not sure about.

Thank you both @DaveMaxwell and @fretburner. I think I understand the concept a little better now. I came from Java, so Javascript is a little hard for me to grasp. Let me see if I got this right. So with Java, when I create a class, I define all of its properties. I can declare them private or public like this:

private int someNum = 10;
public float someFloat = 3.14;

I then set the getter and settter methods while I’m defining the class. So with Javascript, the “this” makes everything private. I’m guessing only methods I have defined in my class would be able to work on the private properties, and it’s just better to define my public methods using Class.prototype.method = function(){}. Is that about right??

No, when you call a constructor function using the new keyword (e.g new Album()), within the constructor this refers to the new instance being created. Whatever values or functions you assign to this will be added to each instance of the object that you create (and will be ‘public’).

Assigning properties or functions to an object’s prototype means that they are not attached to an instance of Album directly. You can kinda think of them as being attached to the Album ‘class’. Each instance of Album that you create has a link back to this prototype object, so one copy of a method can be shared among all instances. This is why it’s more memory efficient.

To make a value/method private, you don’t attach it to the prototype or the instance… you declare it with the var keyword inside of the constructor:

var Person = function(name) {
    var _name = name;  // property is 'private'

    this.getName = function() {
        return _name;
    }
}

var Brian = new Person('Brian');

Brian._name; // undefined
Brian.getName(); // 'Brian'
1 Like

@fretburner I see. That makes a lot of sense. Thank you for helping me understand the logic in that.

The opposite - this makes it public.

Who mentioned Cutler earlier?

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.