There's an error thrown due to sounds
being a scoped (or private) variable to your makeSound
function.
Move it out of the function and it will work. Here's a fiddle demonstrating: http://jsfiddle.net/akx19Loq/
A bit more on variable scope (from MDN)
When you declare a variable outside of any function, it is called a global variable, because it is available to any other code in the current document. When you declare a variable within a function, it is called a local variable, because it is available only within that function.
EDIT
Hi Vipul,
Sure, I'll be happy to explain! Let's break down what happened in our checkGuess
logic.
We get the user's input and store it as a variable, usrInput
.
var usrInput = document.getElementById("guess").value;
We then check to see if the usrInput
variable matches either "Cow" or "Dog". There is also an additional check for either sounds[0]
or sounds[1]
. These are required because an animal must be associated with the sound (a cow can only "moo", and a dog can only "woof").
if (usrInput == "Cow" && sounds[0]) {
// Handle correct guess
}
However, there is an issue with the check && sounds[0]
(which is "moo"), will always evaluate true (due to how JavaScript evaluates booleans
- that is, 0
, false
, null
, and undefined
are all false/falsey
, but 1
, true
, "yes"
, or []
are true/truthy
- which you seem to understand from your comments regarding ==
and ===
).
So, if the question was "What animal says woof", and you guess "Cow", you will win because usrInput
IS definitely equal to Cow
, and sounds[0]
(or woof) is always true
. So we need to add an additional check. That's why we add:
var sound = document.getElementById("soundDisplay").textContent
The animal sound is determined from makeSound
. However, we don't store the sound in a place that is accessible to our checkGuess
function (this is related to "scope" in JavaScript), we need to get the value of the sound from the span
element (using textContent - I could have used innerHTML, but textContent makes more sense here...)
Now that we have the sound, we can properly check for the question "What animal says woof". When a user guesses "Cow", the usrInput == "Cow"
will still be true, but sounds[0] == sound
will evaluate to false since "moo" does not equal "woof".
Hopefully this explains why both checks are required in the if
AND else
statement. As for why three (===
), you're definitely correct - type is not involved here, but ===
is considered good practice to follow when writing JavaScript (nothing to do with array, just the truthy/falsey aspect of JavaScript).
As for developing your answers - you nailed it right on the head! Practice is definitely key! I would recommend you continue reading your book, and be aware of the following books: http://eloquentjavascript.net/ (Free to read online, available in book form - great book to start with as a newbie) and Professional JavaScript for Web Developers (By Zakas). In addition, Crockford's "JavaScript, The Good Parts" is always a recommended resource (Personally, it wasn't until this book that I switched from ==
to ===
for all comparisons, not just when I needed to do a value and type check.)
Also, be sure to understand how the console
works! Check out: https://developer.chrome.com/devtools/docs/console to learn more about this. The console, along with reading Eloquent JavaScript, will allow you to participate as you read.
Another tip - Continue participating in StackOverflow! As you're learning, use stackoverflow as a resource. Read other people's questions and try to answer them (even if you don't submit your answer). If you can't find the solution, see what others did and try to understand how their answers work. Ignore the "gamification" aspect of stackoverflow (getting an answer accepted is always nice, but learning from experienced developers is way more beneficial to you as developer!)
Finally, take up a personal project on something you're passionate about! Your passion will fuel your desire to continue learning the technology.
BTW, Here's a refactored version of your game logic with comments:
http://jsfiddle.net/qadnyt6d/
/* The following randomly selects an animal and returns animal object,
assigning to the variable "selectedAnimal"
Note the paranthesis around the function and at the end,
or (function(){})();
This is an immediately invoked function expression, or IIFE.
As you continue to learn, you will soon see how powerful this is!
http://stackoverflow.com/questions/6340874/a-javascript-function
*/
var selectedAnimal = (function() {
// Array of animals
var animals = [
{
name: 'dog', says: 'woof'
},
{
name: 'cow', says: 'moo'
},
{
name: 'cat', says: 'meow'
}
];
// Return randomly selected animal
return animals[Math.floor(Math.random() * animals.length)];
})();
// Event handler bound to button
function checkUserInput() {
var usrInput = document.getElementById('guess').value;
// We construct a new Regular Expression to test.
// The 'i' denotes case-insensitive, so 'Cat' and 'CAT'
// and 'cat' are all matched
var regex = new RegExp(selectedAnimal.name, 'i');
if (regex.test(usrInput)) {
alert('Congrats! You guessed the right animal!');
} else {
alert('Sorry, that is not correct!');
}
}
// Bind window onload event listener, updates span in HTML with correct animal name
window.onload = function() {
// Display in DOM
document.getElementById("soundDisplay").innerHTML = selectedAnimal.name;
}
Good luck Vipul!
BTW, Here's a challenge for you - can you take the new version and refactor the code so that after a user wins, a new game begins?