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

Jonathan Fish
Jonathan Fish
7,788 Points

Random Quote Generator: calling array.length within a function

Hi, I am at a breaking point with this because I feel like I am making a really easy mistake but after searching the forums, stack overflow and google I can't seem to find a fix. At the top of my code (using Atom) I have defined an array like this:

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"
  },
];

I have reviewed the documentation on MDN and I believe my syntax is correct. I have square brackets for the array, each object within the array is separated by a comma, and all object attributes are separated by commas. However, when I attempt to use the .length property within a function:

function getRandomQuote() {
  let randomQuote = quotes[Math.floor(Math.random()* quotes.length)]
  if(usedQuotes.length == quotes.length){
    usedQuotes = []
  }
  if(usedQuotes.Contains(randomQuote)== false){
    usedQuotes.push(randomQuote);
    console.log(randomQuote);
    return randomQuote;
  } else {
    getRandomQuote();
  }
};

I get an error code saying the .length property cannot be used on undefined and it says quotes is undefined. I have usedQuotes defined as an empty array outside of the function. I am using Chrome to test my code. I'm sorry if this is an easy question but I cannot figure it out. I don't think the function is quite right for the project task but it's just a framework for my initial idea to solve the problem, I am not concerned with fixing the function, just with figuring out why .length is undefined for quotes. Thank you so much for any help you can give.

3 Answers

Keenan Johnson
Keenan Johnson
13,841 Points

Two things:

In regards to your first error in which 'usedQuotes' is defined outside of the function, my guess it's that it's an issue with the scope, so that particular variable isn't available in that function scope. The second thing I caught is that instead of usedQuotes.Contains() (this should be lower case as well unless you created your own Contains function), you probably are meaning to use usedQuotes.includes().

Working solution:

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"
  },
];

function getRandomQuote() {
  let randomQuote = quotes[Math.floor(Math.random()* quotes.length)]
  let usedQuotes = []; // defined an empty array for usedQuotes variable here
  if(usedQuotes.length === quotes.length){
    usedQuotes = []
  }
// used .includes() function -> MDN Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes?v=example
  if(usedQuotes.includes(randomQuote) === false){
    usedQuotes.push(randomQuote);
    console.log(randomQuote);
    return randomQuote;
  } else {
    getRandomQuote();
  }
};

getRandomQuote();

Another note: I would use strict equality (===) for comparison instead of (==)

Hopefully this makes sense and fixes the issue!

Jonathan Fish
Jonathan Fish
7,788 Points

Thanks Keenan, I did not know about the includes function so I had created a function called Contains but the includes() is much better. Also, thanks you for your notes about strict equality, I will switch to that throughout my code. However, I am still receiving an undefined error for the quotes[] array. I have read up on scope and the quotes[] array is defined outside of the function so it should have a global scope, allowing me to call it within the function but the specific error I receive is : Uncaught TypeError: Cannot read property 'length' of undefined and it points specifically to: quotes.length I've never had a problem calling a global array within a function before so I'm extremely confused.
If you can help with this, I'd appreciate it but I'm also grateful for the help you were already able to provide.

Edit: I managed to get past this error by moving the entire quotes[] array inside of the function

function getRandomQuote() {
var usedQuotes = [];
  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"
    },
  ];
  var randomQuote = quotes[Math.floor(Math.random()* 10)];
  if(usedQuotes.length === 10){
    usedQuotes = [];
  }
  if(usedQuotes.includes(randomQuote)=== false){
    usedQuotes.push(randomQuote);
    console.log(randomQuote);
    return randomQuote;
  } else {
    getRandomQuote();
  }
}

but the project requirements state that the quotes array should be accessible in the global scope. So I'm really confused why it was necessary to define the quotes array within the function instead of before it in the global scope.

Keenan Johnson
Keenan Johnson
13,841 Points

Hmm. If you copy and paste the code block I wrote as a snippet in Chrome and click 'Run snippet' (or Ctrl + Enter) you get an error? Using the var keyword for quotes, it is a part of the global scope of that file and does not need to be defined from within the function to be accessed. If my code doesn't work, try moving the quotes array outside of the function and then post the snippet back here. I'll try to replicate the error and provide a fix :)

Jonathan Fish
Jonathan Fish
7,788 Points

Thanks again for the tip Keenan. I took your advice and copied your quotes[] array and replaced my own, outside of the function again, and for some reason, it fixed everything. I didn't even replace the function, just swapped out the array and suddenly it was no longer throwing the undefined error. I have compared my quotes[] array to the one you posted and cannot find the difference so I am incredibly confused but my problem is solved so I'm eternally grateful!

Keenan Johnson
Keenan Johnson
13,841 Points

That is weird haha and now i'm interested what the differences were! But at any rate, i'm really glad I was able to help!