By the end of this lesson, you should:
- Be familiar with the concept of "Data Types".
- Understand what input validation means and why we use it.
- Know how to use the
Number()
function to convert a string to a number. - Know what the
NaN
data type is.
So far in any of our dice-guessing games, the program doesn't restrict players from entering "bananas", 38373, or any value other than 1 to 6. In the way we've written our code so far, there may not be errors for invalid input, but there will be situations in Coding Basics where invalid input causes syntax or logical errors. To preempt these errors, we may wish to guide the player by providing feedback when their input is invalid.
We will use our dice game to demonstrate input validation. We'll first see how to detect if the player typed in a number, then we'll detect if the player's number is within the desired range of 1 to 6.
When running the main
function via clicking the submit button, the input
parameter will always be a string data type. The input
string may sometimes contain number characters - e.g. "5", "9383733", or a combination of letter with number characters, e.g. "abc123", but the variable will nonetheless be of type string.
How can we check if the characters in input
are only numbers? If we expect only number characters, how can we convert input
to be a number and not a string?
We can try to convert a variable from string to number type with the Number
function. If the string value has only number characters in it, Number
will transform the string into a number.
var input = '444';
var inputNum = Number(input); // inputNum is 444
{% hint style="warning" %}
In certain projects and exercises during Coding Basics, we will compare the value of input
with a number as part of program logic. This can result in unexpected errors if we do not transform input
from string to number first.
Whenever we expect input
to represent a number, we should always cast it to a number with Number(input)
before using it. This will help prevent unexpected errors where input
may not equal what we expect, for example when comparing "1" with 1.
{% endhint %}
When we use the Number
function to convert a value that isn't only numbers, Number
may return a NaN
value. NaN
stands for "Not a Number". For example, the following code generates NaN
.
var input = 'papayas';
Number(input);
NaN also occurs when we attempt a math operation that doesn't result in a valid number. The following are examples.
2 * 'chocolate';
'dogs' / 32;
0 / 0;
Note that NaN
is a valid value in JavaScript, like 0
or 1
. The following examples store NaN
in variables.
var count = NaN;
var count = 'papayas' * 12;
var input = 'papayas';
var inputCount = Number(input);
We can use NaN to write logic like the following.
If we try to convert a value to a number and we get the result NaN, then the value is not a number.
To help us implement our logic above, JavaScript provides a Number.isNaN
function that returns whether a given value has value NaN
. This is because a direct comparison of a value with NaN
doesn't work in JavaScript. The following code would not work as we might expect.
// this will say FALSE, which is incorrect
Number('bananas') == NaN;
The following is an example of Number.isNaN
, which is built-in to JavaScript. Number.isNaN
returns a boolean value.
var input = 'hello';
var result = Number(input);
console.log(Number.isNaN(result));
To complete our logic, we might add a conditional such that our code looks like the following.
if (Number.isNaN(Number(input))) {
myOutputValue = 'sorry please enter a number.';
} else {
// insert regular app logic here
}
Now that we've verified that input
contains only numbers, let's verify that input is between 1 and 6. We could write a long conditional like the following...
if (
input == 1 ||
input == 2 ||
// ... etc
) {
// ...
}
...or we could express this range with comparison operators less than or equal to (<=
) and greater than or equal to (>=
). The if conditional in both examples evaluates to true
when input
is between 1 and 6.
// if number is greater than or equal to 1 AND less than or equal to 6
if (input >= 1 && input <= 6) {
// number is between 1 and 6
}
Note the functionality of the 2nd example is the same as the 1st, easier to understand, and easier to write, especially when we have a wider range, for example with a 20-sided dice. There are other ways to validate a number range, for example with less than (<
) and greater than (>
) operators like we do below.
Our dice game code looks like the following with input validation.
var rollDice = function () {
// produce a decimal between 0 and 6
var randomDecimal = Math.random() * 6;
// remove the decimal
var randomInteger = Math.floor(randomDecimal);
// add 1 to get a number between 1 and 6 inclusive
var diceNumber = randomInteger + 1;
return diceNumber;
};
var main = function (input) {
var myOutputValue = '';
// first check if input is a number
if (Number.isNaN(Number(input)) == true) {
myOutputValue = 'sorry please enter a number.';
} else {
// then check if input is between 1 and 6
if (input < 1 || input > 6) {
myOutputValue = 'sorry please enter a number from 1 - 6';
} else {
// the input is 1-6, go ahead with the dice game
var randomDiceNumber = rollDice();
if (randomDiceNumber == input) {
myOutputValue = 'you win';
} else {
myOutputValue = 'you lose';
}
}
}
return myOutputValue;
};
You may notice that the above example has several levels of nested if and else statements. If we have more types of input validation, this can make our code unnecessarily complex. Luckily, there is a simple way to reduce complexity by using multiple return
statements in our functions.
Notice the multiple return
statements in the main
function below. This simplifies our logic by reducing nesting of if and else blocks. Functions exit after return
statements, i.e. nothing in the function is executed after return
, making return
statements convenient ways to exit our logic if input is invalid.
var rollDice = function () {
// produce a decimal between 0 and 6
var randomDecimal = Math.random() * 6;
// remove the decimal
var randomInteger = Math.floor(randomDecimal);
// add 1 to get a number between 1 and 6 inclusive
var diceNumber = randomInteger + 1;
return diceNumber;
};
var main = function (input) {
var myOutputValue = '';
// first check if input is a number
if (Number.isNaN(Number(input)) == true) {
myOutputValue = 'sorry please enter a number.';
return myOutputValue;
}
// then check if input is between 1 and 6
if (input < 1 || input > 6) {
myOutputValue = 'sorry please enter a number from 1 - 6';
return myOutputValue;
}
// the input is 1-6, go ahead with the dice game
var randomDiceNumber = rollDice();
if (randomDiceNumber == input) {
myOutputValue = 'you win';
return myOutputValue;
}
myOutputValue = 'you lose';
return myOutputValue;
};
Add input validation to your Projects and Exercises as practice.