Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript

Jonathan Fish
Jonathan Fish
7,788 Points

Random Quote Generator: Problem with array.property becoming undefined intermittently.

Hello, I am working my way through the Random Quote Generator Project for JavaScript. I have reached a point where I have created an array of quotes, a function to generate a random quote while checking if that quote has already appeared, and a function to make the quote appear on the page. I have gotten it to cycle through the list of quotes without repeats several times but I have this strange undefined error that seems to randomly appear and becomes more frequent as the button is clicked more. Here is my current code:

var quotes = [
  {
    quote: "I'm not sure if I was the first man in space or the last dog.",
    source: "-Yuri Gagarin",
    year: "1961",
    tags: "Humor",
  },
  {
    quote: "'We’ll never survive!' 'Nonsense. You’re only saying that because no one ever has.'",
    source: "-William Goldman",
    citation: "The Princess Bride",
    year: "1987",
    tags: "Inspirational",
  },
  {
    quote: "You know, Hobbes, some days even my lucky rocket ship underpants don't help.",
    source: "-Bill Watterson",
    citation: "Calvin and Hobbes",
    tags:"Humor"
  },
  {
    quote: "You people talk about the living and the dead as if they were two mutually exclusive categories. As if you cannot have a river that is also a road, or a song that is also a color.",
    source: "-Neil Gaiman",
    citation:"American Gods",
    year: "2001",
    tags: "Spirituaity"
  },
  {
      quote:"Yet man will never be perfect until he learns to create and destroy; he does know how to destroy, and that is half the battle.",
      source: "-Alexandre Dumas",
      citation: "The Count of Monte Cristo",
      year: "1844",
      tags: "Humanity"
  },
  {
      quote:"Never let your sense of morals prevent you from doing what is right.",
      source: "-Isaac Asimov",
      citation: "Foundation",
      year: "1951",
      tags: "Spirituality"
  },
  {
      quote: "Let's think the unthinkable, let's do the undoable. Let us prepare to grapple with the ineffable itself, and see if we may not eff it after all.",
      source: "-Douglas Adams",
      citation: "Dirk Gently's Holistic Detective Agency",
      year: "1987",
      tags: "Inspirational",
  },
  {
      quote: "A creative man is motivated by the desire to achieve, not by the desire to beat others.",
      source: "-Ayn Rand",
      tags: "Inspirational"
  },
  {
      quote: "I'm not dumb. I just have a command of thoroughly useless information.",
      source: "-Bill Watterson",
      citation: "Calvin and Hobbes",
      tags:"Humor"
  },
  {
      quote:"A bone to the dog is not charity. Charity is the bone shared with the dog, when you are just as hungry as the dog.",
      source:"-Jack London",
      tags:"Humanity"
  },
];

//empty array to hold used quotes
let usedQuotes = [];

// function for finding a random quote without repeats
function getRandomQuote() {
  let randomQuote = quotes[Math.floor(Math.random()* quotes.length)]
  if(usedQuotes.length === quotes.length){
    usedQuotes = []
  }
  if(usedQuotes.includes(randomQuote) === true){
    getRandomQuote();
  } else {
    usedQuotes.push(randomQuote);
    console.log(randomQuote);
    return randomQuote;
  }
};



// print quotes to page
function printQuote() {
  let quotation = getRandomQuote();
  let fullQuote = '';
  let outputQuote = document.getElementById('quote-box');
  fullQuote += '<p class="quote">' + quotation.quote + '</p>';
  fullQuote += '<p class= "source">' + quotation.source;
//check for optional properties
  if(quotation.hasOwnProperty('citation')=== true){
    fullQuote += '<span class= "citation">' + ' '+ quotation.citation + '</span>';
  }
  if(quotation.hasOwnProperty('year')=== true){
    fullQuote += '<span class= "year">' + ' '+ quotation.year + '</span>';
  }
  if(quotation.hasOwnProperty('tags')=== true){
    fullQuote += '<span class= "tags">' + ' '+ quotation.tags + '</span>';
  }
  fullQuote += '</p>';
  outputQuote.innerHTML = fullQuote
}
//Button click event listener
document.getElementById('loadQuote').addEventListener("click", printQuote, false);

The specific line which returns undefined is in the printQuote() function:

 fullQuote += '<p class="quote">' + quotation.quote + '</p>';

At very random intervals it will throw an error that says: undefined is not an object (evaluating 'quotation.quote')

However, if I keep clicking the button it will work. It doesn't happen on any specific quote either, I have watched the console log and a quote will work perfectly fine one time and then another time that same quote will throw this error and not appear on the page. If I click the button when this happens it will just move on to the next quote. The errors start out infrequent but I have noticed that if I click the button for a while, the errors become more frequent and I can eventually get instances where no quote is displayed on the screen or nothing happens for several button clicks.

I am wondering what the problem could be. My current guess is that it could have something to do with the way I am checking for repeats in the first function. I have it checking if an object is in an array, adding it to the array if it isn't and emptying the array once it is full. This seemed like a simple solution but maybe there is something happening here that I don't know about.

Please help! I would really appreciate it if someone could shed some light on this. Thanks.

1 Answer

Jonathan Fish
Jonathan Fish
7,788 Points

Solved the problem! The random error was coming from the second function where I defined the variable quotation and made it equal to the getRandomQuote() function. This was creating a problem anytime the getRandomQuote function followed the if() branch which made it call itself. I fixed this by eliminating the quotation variable, making the randomQuote variable in the first function a global variable and then simply calling getRandomQuote() in the second function and replacing all instances of the quotation variable with the randomQuote variable. Here's the working, non-repeating generator for anyone with similar issues.

//quotes array of objects
var quotes = [
  {
    quote: "I'm not sure if I was the first man in space or the last dog.",
    source: "-Yuri Gagarin",
    year: "1961",
    tags: "Humor",
  },
  {
    quote: "'We’ll never survive!' 'Nonsense. You’re only saying that because no one ever has.'",
    source: "-William Goldman",
    citation: "The Princess Bride",
    year: "1987",
    tags: "Inspirational",
  },
  {
    quote: "You know, Hobbes, some days even my lucky rocket ship underpants don't help.",
    source: "-Bill Watterson",
    citation: "Calvin and Hobbes",
    tags:"Humor"
  },
  {
    quote: "You people talk about the living and the dead as if they were two mutually exclusive categories. As if you cannot have a river that is also a road, or a song that is also a color.",
    source: "-Neil Gaiman",
    citation:"American Gods",
    year: "2001",
    tags: "Spirituaity"
  },
  {
      quote:"Yet man will never be perfect until he learns to create and destroy; he does know how to destroy, and that is half the battle.",
      source: "-Alexandre Dumas",
      citation: "The Count of Monte Cristo",
      year: "1844",
      tags: "Humanity"
  },
  {
      quote:"Never let your sense of morals prevent you from doing what is right.",
      source: "-Isaac Asimov",
      citation: "Foundation",
      year: "1951",
      tags: "Spirituality"
  },
  {
      quote: "Let's think the unthinkable, let's do the undoable. Let us prepare to grapple with the ineffable itself, and see if we may not eff it after all.",
      source: "-Douglas Adams",
      citation: "Dirk Gently's Holistic Detective Agency",
      year: "1987",
      tags: "Inspirational",
  },
  {
      quote: "A creative man is motivated by the desire to achieve, not by the desire to beat others.",
      source: "-Ayn Rand",
      tags: "Inspirational"
  },
  {
      quote: "I'm not dumb. I just have a command of thoroughly useless information.",
      source: "-Bill Watterson",
      citation: "Calvin and Hobbes",
      tags:"Humor"
  },
  {
      quote:"A bone to the dog is not charity. Charity is the bone shared with the dog, when you are just as hungry as the dog.",
      source:"-Jack London",
      tags:"Humanity"
  },
];

//empty array to hold used quotes
let usedQuotes = [];
//global variable to hold randomly generated quote
var randomQuote;
// function for finding a random quote without repeats
function getRandomQuote() {
   randomQuote = quotes[Math.floor(Math.random()* quotes.length)]
  if(usedQuotes.length === quotes.length){
    usedQuotes = []
  }
  if(usedQuotes.includes(randomQuote) === true){
    getRandomQuote();
  } else {
    usedQuotes.push(randomQuote);
    console.log(randomQuote);
    return randomQuote;
  }
};



// print quotes to page
function printQuote() {
  getRandomQuote();
  let fullQuote = '';
  let outputQuote = document.getElementById('quote-box');
  fullQuote += '<p class="quote">' + randomQuote.quote + '</p>';
  fullQuote += '<p class= "source">' + randomQuote.source;
//check for optional properties
  if(randomQuote.hasOwnProperty('citation')=== true){
    fullQuote += '<span class= "citation">' + ' '+ randomQuote.citation + '</span>';
  }
  if(randomQuote.hasOwnProperty('year')=== true){
    fullQuote += '<span class= "year">' + ' '+ randomQuote.year + '</span>';
  }
  if(randomQuote.hasOwnProperty('tags')=== true){
    fullQuote += '<span class= "tags">' + ' '+ randomQuote.tags + '</span>';
  }
  fullQuote += '</p>';
  outputQuote.innerHTML = fullQuote
}
//Button click event listener
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
Steven Parker
Steven Parker
216,071 Points

Congrats. I'd saved this question but when I came back to it I see you resolved it yourself. Good job! :+1: