Search code examples
javascriptoopprototypejs

JavaScript prototype function not available from constructed object


For the code below, I am getting the following error on the second line of the GameStatsPanel function:

"Uncaught TypeError: Object #Timer has no method 'start'"

I'm really quite confused why this is happening - I have a feeling I'm missing something simple somewhere but I need enlightened. Feel free to check out the issue by going to www.letsplayglobalgames.com and selecting the 'Play!' option from the homepage. Let me know if you need more details.

function GameStatsPanel() {
    this.timer = new Timer();
    this.timer.start(); /* error is thrown here */
}
function Timer() {
    this.container = document.getElementById('game_time');
    this.current_flag_time_start;
    this.current_flag_time_stop;
    this.time_start = new Date();
    this.time_stop;
    this.time_difference;
    this.current_flag_time_difference;
}
Timer.prototype.start = function() {
    this.current_flag_time_start = new Date();
}

Solution

  • You're invoking the Timer constructor before the Timer.prototype has a chance to be set up with your methods.

    The Timer function is available, because function declarations are "hoisted", and therefore available immediately.

    The extensions to Timer.prototype are not "hoisted", so your Timer has an unmodified .prototype when you do new Timer.

    gameStatsPanel = new GameStatsPanel(); // Invoking this too soon. Put it and
    // ...                            // anything else that uses the constructors at
                                      // the bottom so the prototypes can be set up.
    function main() {
       // ...
    }
    
    function GameStatsPanel() {
        this.timer = new Timer(); // The `Timer.prototype` extensions haven't run yet
        // ...
        this.timer.start(); // .start doesn't yet exist
    }
    
    // ...
    
    function Timer() {
        // ...
    }
    
    // ...
    
     // *Now* the .start() method is getting added.
    Timer.prototype.start = function () {
        this.current_flag_time_start = new Date();
    }
    
    // ...