3

I have strange error when I decided to build ordinary web-form validation with classic javascript. There are several "onblur" handlers for input text fields and one "form-submit" handler.

When I use them like that:

function loginCheck() {
  ... return true of false 
}

function passwordCheck() { 
   ...
}

function formValidation() {
  return loginCheck() && passwordCheck();
}

It doesn't work as I expect: "passwordCheck" never called if loginCheck is failed!

Finally I have workaround

function formValidation() {
  ok = loginCheck();
  ok &= passwordCheck();
  return ok;
}

Now password check is executed. But when I choose:

function formValidation() {
      ok = loginCheck();
      ok = ok && passwordCheck();
      return ok;
    }

passwordCheck is never called again if loginCheck failed.

Moreover: loginCheck & passwordCheck return boolean values, but &= operator covert it to "0" or "1". "0" doesn't work for my onsubmit="return checkForm" handler. I have to convert my &= result to boolean once again:

function formValidation() {
      ok = loginCheck();
      ok &= passwordCheck();
      return ok != 0;
    }

It is a normal behavior for javascript engines ?

Andrew Florko
  • 7,672
  • 10
  • 60
  • 107
  • 5
    `&` is bitwise AND and will always return a number. `&&` is logial AND and will return the value of the expression which determines the overall outcome. A shortcut to convert any value into its boolean equivalent is to use double negation `!!`. – Felix Kling Oct 22 '11 at 10:17
  • Can somehow change the horrible title? I can't think of something that's clear and still attractive. – Lekensteyn Oct 22 '11 at 10:19
  • Some refactoring is in order if you need to do a password check after a login check fails. – hyperslug Oct 22 '11 at 10:23

3 Answers3

7

Yes, it's normal. It's called a short-circuit evaluation and is both handy and very common (i.e. is present in a lot of languages (C, C++, Java, Perl, many others), not just JavaScript).

Mat
  • 202,337
  • 40
  • 393
  • 406
2

That is the way it should be!

Quote from wikipedia : the logical conjunction (a.k.a. &&) "results in true if both of its operands are true, otherwise the value of false."
In other words, if the first operand is false, there is no need to proceed with the evaluation of the second one because the result will always be false.

So an expression like

if(condition1 && condition2)

is equivalent to

if(condition1){
    if(condition2){

    }
}

So you see that if the first condition is false, there is no need to continue evaluating your expression, because the answer will be unchanged.

gion_13
  • 41,171
  • 10
  • 96
  • 108
0

If you want to explicitly run both functions, you can choose to only run && when both have been evaluated:

var l = loginCheck(),    // will evaluate
    p = passwordCheck(); // will evaluate

return l && p;           // if l failed, p will be ignored, but both functions
                         // have been evaluated anyway
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • `return loginCheck() | passwordCheck();` does the same thing in one line, but in this instance why you would want to do the password check if the login failed is a mystery. – user207421 Oct 22 '11 at 10:23
  • @EJP: True, but then again that returns a number. I was just posting this as an alternative to the sophisticated `&=` way. – pimvdb Oct 22 '11 at 10:39
  • @EJP because my checks reoder UI. I'd like to show current errors to user – Andrew Florko Oct 22 '11 at 12:35
  • @pimvdb The OP'2 two methods both return boolean so this line returns a boolean too. It returns a number if the methods return a number. – user207421 Oct 23 '11 at 01:02
  • @EJP: Well not exactly. `(true | false) === 1`. – pimvdb Oct 23 '11 at 09:06