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

Issue with my conditional statements

Im trying to write an fake ATM program machine program that allow 4 or 6 digits pin codes strictly, not 5 not >6 or <4 strictly 4 and 6, Such as the following conditions scenarios apply validatePIN("1234") === true validatePIN("12345") === false validatePIN("a234") === false

function validatePIN (pin){
  var pin = ""; 

  if (pin.length !=4 || pin.length !=6) {
    return false;
   }

  else {
   return true;
   } 
}

when i test the function the program returns "false" correctly as it should for scenarios with pins that are not 4 or 6 digits exactly. However it keeps on returning false for any other scenarios that are still within the 4 or 6 digit limit like ("1234"), ("123456") or ("1111") etc... It seems as though my second conditional statement is not considered at all regardless of what condition if pass through.

Any feedback appreciated.

4 Answers

andren
andren
28,558 Points

The first line of your program sets the pin variable to an empty string, so everything you pass into the function will be ignored. But that is not actually the main issue with your code.

The main issue occurs because you use the || (OR) operator within the if statement. The OR operator will look at the conditions and return true as long as one of the conditions evaluates to true. If you enter 4 then the condition that the number is not 6 is true, if you enter 6 then the condition that the number is not 4 is true.

The reason all numbers fail is that it's impossible for a number to be both 4 and 6 at the same time, which is technically what needs to happen for the if statement not to run.

You can fix this issue by using the && (AND) operator instead. That looks at both conditions and only returns true if both of them are true. So unless the number is not 4 and not 6 it won't run, which is of curse your intended behavior.

Edit:

Also your code currently only deals with the length of the pin, it does nothing to check whether the pin entirely consists of numbers, I assume you are aware of that and intend to work on that yourself once this issue has been resolved. But if you need help with that too then I can provide a solution for it.

Benjamin Larson
Benjamin Larson
34,055 Points

Beat me too it, I should refresh my old browser tabs before answering questions haha. But good example that there's always more than one way to solve a problem.

andren
andren
28,558 Points

Don't worry, I've certainly made my share of lengthy answers that ends up being posted a while after the question was answered as well :smile:.

And yeah there definitively are many varied ways of solving the same issue. That's part of the reason why I personally don't mind it when multiple people end up answering the same question. Different people often come up with slightly different solutions, and that can be helpful and educational on it's own.

Benjamin Larson
Benjamin Larson
34,055 Points

There's a couple issues with your code preventing this. The first one is that, within the function you are declaring the var pin and assigning it an empty string. This is effectively overwriting any argument you pass into it, so it will always evaluate an empty string, and therefore, always be false.

The second problem is the logic in your conditional if statement. I understand the logic you are using but it's not the way it's actually being evaluated. You were right that it never seems to evaluate the second half of the expression. The way a conditional || (OR) statement works, is that it looks at each condition and if either of them evaluates to true, then the conclusion is true. Conditional OR statements also short-circuit, meaning that if the first case is TRUE, then there's no point in checking the second case, because it will evaluate to TRUE in either case.

In your case: IF EITHER (pin.length != 4) OR (pin.length ! =6) is TRUE, then the result is TRUE.

Think carefully about your code now. If it receives any length other than 4, the first half will evaluate to TRUE and it won't even check if pin.length !=6.

It's also not easy to spot, because when the IF condition evaluates to TRUE, you then have it return FALSE. This is valid and sometimes useful, but often confusing.

Here is one way you might solve this:

function validatePIN(pin) {

  if (pin.length === 4 || pin.length === 6) {
    return true;
  } else {
    return false;
  }
}

Thanks for the feedback guys. Benjamin Larson that explanation makes a lot of sense. I was overthinking because initially i thought about starting the condition with if (pin.length === 4 || pin.length === 6)and have it return true but once i noticed the program didn't seem to consider the second conditional statement i figured id start with something false so that the program could keep looking through the conditional until it returned true.

andren
Taking into consideration both of you guys feedback this is what i came with to finalize it and also address the fact that the program needs to check whether the pin entirely consists of numbers However when i type a pin that contains characters other than digits like ('a234') or ('.234') it returns true instead of false for these scenarios. Any thoughts ?

function validatePIN(pin){ 
  if (pin.length === 4 || pin.length === 6) {
    return true;
   }
  else if( isNaN(pin)===true) {
   return false;
   } 
   else {
     return false;
   } 
} 
andren
andren
28,558 Points

Amir Bizimana If statements are evaluated from top to bottom, and else if and else statements only run if the first if statement evaluates to false.

Since "a234" does have a length of 4 the first if statement will run, which means that the else if is not executed at all. And even if that was not the case, once you return a value the method stops executing, so even if you didn't use if/else if statements the method would stop once the if statement ran anyway.

The solution to that issue is pretty simple, move the isNaN check to the top. Like this

function validatePIN(pin){ 
  if(isNaN(pin)) {
    return false;
  } 
  else if (pin.length === 4 || pin.length === 6) {
    return true;
  }
  else {
    return false;
  } 
} 

Also since isNaN returns true of false on its own you don't need to compare it to true, that is redundant. So I removed that comparison.

Edit:

You could also make the if statement more compact by combining the if and else if into one check like this:

function validatePIN(pin){ 
   if ((pin.length === 4 || pin.length === 6) && !isNaN(pin)) {
     return true;
   }
   else {
     return false;
   } 
} 

That is a bit more complicated to read, but it essentially says "if pin is 4 or 6 and it's not not a number then return true". I had to wrap the first two conditionals in parentheses to make sure they are evaluated first.

Benjamin Larson
Benjamin Larson
34,055 Points

I do most of my programming in C#, Java and PHP so I'll have to think about this one, but even with andren's improved function, there are still exceptions such as:

validatePIN("1.23");

Are there any other JavaScript functions that could check this without using Regular Expressions? +1 to strongly typed languages that don't have this problem haha

andren
andren
28,558 Points

Benjamin Larson Ops, you are right. I forgot to use . when testing the code. The simplest (but somewhat lazy and hacky) way to solve that issue would just be to explicitly check for the dot like this:

function validatePIN(pin){ 
   if ((pin.length === 4 || pin.length === 6) && !isNaN(pin) && !pin.includes(".")) {
     return true;
   }
   else {
     return false;
   } 
} 

That works, but it's admittedly not very elegant. I spend a decent amount of time coding in JavaScript (though I prefer to use TypeScript whenever i can get away with it) but I can't say I deal with number input validation all that often, so I don't have any good elegant solution I can think of at the top of my head.

I also tend to prefer strongly typed languages. Auto conversions might be nice for people just starting out with programming but they become a pain to deal with later.

Benjamin Larson
Benjamin Larson
34,055 Points

Yeah, I tried a different way, which requires the input be entered as an integer and not a string.

function validatePIN(pin){ 
   if (Number.isInteger(pin) && (pin.toString().length === 4 || pin.toString().length === 6)) {
     return true;
   }
   else {
     return false;
   } 
}

Searching for the "." is better than mine because Number.isInteger() isn't supported in older versions of IE. There's probably validation packages out there that do this much better and if you're really ambitious Amir, you can learn Regular Expressions to have a lot more control in these situations.

Sam Donald
Sam Donald
36,305 Points

Amir Bizimana - Benjamin Larson - andren

Use RegExp

function validatePIN(pin)
{
    var expression = new RegExp(/^\d{4}$|^\d{6}$/);
    return expression.test(pin);
}
  1. The regular expression /^\d{4}$|^\d{6}&/ will only match a pin with exactly 4 or 6 digits.
  2. The .test() method takes pin and evaluates it against our expression. Returning true or false

See

Im gonna get some learning done on those. Thanks for posting the MDN resources !

Thanks again for the feedback andren and Benjamin Larson ! Guess i need to review the rules surrounding conditional statements. I've made a slight modification to the to the first conditional and added a parseInt() method to the pin because it was still returning true for (".234"). I realized that with (".234") or ("1.23") the isNaN() would evaluate it to false because it seems to overlook the dot and focus on the numbers instead. By strictly parsing the pin for integers with the parseInt() the program will recognize that there is a little intruder in strings like (".234") or ("1.23").

Thank you for the help !

function validatePIN(pin){ 

  if( isNaN(parseInt(pin))) {
   return false;
   } 
  else if (pin.length === 4 || pin.length === 6) {
    return true;
   }
   else {
     return false;
   } 
}
Benjamin Larson
Benjamin Larson
34,055 Points

I hate to be "that guy", but I can technically break that one with:

validatePIN("1234.0")

Sorry...lol