4

i am trying to understand the explanation for this code.

function Test() {
  var a = 0; var b = 0; var c = 0; var d = 0;

  if (a++ && b-- || c++) {
    console.log("if block")
  } else {
    console.log("else block")
  }
  console.log(b);
}

Test();

observation: when we execute this code the value of 'b' is 0; not '-1'. i think A && B is false but when it is again check || with c, it should be true. but when i run the code, else block executes. i am trying to find explanation for that. tried finding it out but didn't find anything helpful.

Peter B
  • 22,460
  • 5
  • 32
  • 69
Groot
  • 171
  • 13
  • Does this answer your question? [Evaluation of the following expression](https://stackoverflow.com/questions/17239286/evaluation-of-the-following-expression) – rtoijala Aug 25 '22 at 12:16
  • 1
    `x++` and `x--` will return what the value of `x` is *before* incrementing/decrementing it. In your example, everything is set to 0 initially. in JavaScript (which I presume is what this is), 0 is evaluated to `false` in an if statement. All 3 of your conditions being `false` makes it go to the `else` block. If you need to evaluate the variable's value after incrementing/decrementing, you can use `++x` or `--x` instead. – Jesse Aug 25 '22 at 19:27
  • 1
    javascript or c++? your code looks like a mix of both. – Yury Tarabanko Aug 27 '22 at 08:55
  • @Jesse , when i execute the code [ assuming the if condition executes before incrementing a,b,c . so it become false.] but when i print a,b,c after if block, it prints a as 1, b as 0. why b is zero ? – Groot Aug 27 '22 at 09:00

1 Answers1

4

Let's take the if statement and break it down.

a++ && b-- || c++

The order of operating with ++ has two variants:

  1. a++ - returns the value of a, then increases by 1
  2. ++a - increases by 1, then returns the new value of a

So the first part, a++ returns a, which when used as a boolean (since this is an if statement) will evaluate as false, and only afterwards it increases a by 1.

An important thing to note now, is that JS has short-circuiting:

If a part of the statement returns a "falsy" result and the rest of the statement relies on said result, the latter part of an expression will not be evaluated.

Take this for instance:

if (1 === 0 && console.log('test')) { 
  // ...
}

You will note that console.log never fires. That is because the && created an implicit condition, where the latter part doesn't need to be evaluated, as the condition preceding it was resolved as false.

Now that we know this, we can see why the else fired, and why the rest of the expression didn't evaluate (thus, leaving b as 0).

  1. a++ - A is returned as 0, which is false in this context, and the if statement immediately fails, thus falling to the else statement.
  2. b-- and c++ were never evaluated, as it was short-circuited.
  3. Therefore, b and c remained 0. You can test that a is indeed 1, but the if statement was not aware of this quite yet.

If you change your code a bit...

if (++a && --b || ++c) {

You will see that you do fall in the if statement log, and not the else.

This is because:

  1. ++a will evaluate to 1, which is truthy
  2. --b will evaluate to -1, which is also truthy.
  3. Since the previous was truthy, there is no need to check the or that follows it, as the condition was already fullfilled.

a will be 1, b will be -1, and c will remain 0.

function Test() {
  let a = 0, b = 0, c = 0, d = 0;

  if (++a && --b || ++c) {
    console.log("if block")
  } else {
    console.log("else block")
  }
  console.log({ a, b, c });
}

Test();
casraf
  • 21,085
  • 9
  • 56
  • 91
  • 1
    Nice answer, but this part _"c++ were never evaluated, as it was short-circuited."_ isn't correct. `c++` is evaluated, but again it returns `0` so the condition isn't satisfied. That's due to `&&` having higher operator precedence than `||`, so the condition is evaluated as `(a++ && b--) || c++`, so you'll `c` is actually `1`, not `0` – Nick Parsons Aug 27 '22 at 09:36
  • Thanks! But you can run the code and see that c is still 0, even when I used `++c` to return only after increasing. The AND operation short circuits it anyway before the expression is completely parsed. The OR has its own short circuiting which doesn't get to do its operation at this point – casraf Aug 27 '22 at 11:42
  • 1
    When running it, I see that `c` is 1, not 0 ([example](https://jsfiddle.net/cwrz6ns5/)). The `||` doesn't short-circuit in OPs condition, the `&&` does though as you've pointed out. As we get `false || c++`, the `c++` is still evaluated. (To clarify, I'm talking about the `a++ && b-- || c++` scenario. In your condition with the prefix increment/decrement the `c` remains 0) – Nick Parsons Aug 27 '22 at 11:56
  • 1
    Ah yes, I see what you mean. Yes, in OPs original code the short circuiting is different than mine. I must have mixed those up a bit when I was explaining and correcting the code. – casraf Aug 27 '22 at 12:04