4

I was testing some stuff on Console on Chrome and then I ran that piece of code:

alert() | window.confirm();
alert() || window.confirm();

My problem was to run both alert and confirm methods in a single line without using semicolon. It turns out that both | and || worked and I can't imagine why it worked, firstly because || means an OR operator which should run one of them not both and secondly | I don't know what it is. Can someone explain what happened and what else should work instead of ;?

testing_22
  • 397
  • 2
  • 11
  • See [What does this symbol mean in JavaScript?](https://stackoverflow.com/q/9549780/4642212) and the documentation on MDN about [expressions and operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators) and [statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements). – Sebastian Simon Sep 08 '20 at 03:22
  • 1
    The [comma operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator) would be more appropriate here. – Sebastian Simon Sep 08 '20 at 03:24
  • The comma operator returns the last value. So, I'd argue that the more appropriate (and clear) here would be not comma operators or ORs or bitwise ORs or whatever, but just 2 lines of code, one for each method, as in [this answer](https://stackoverflow.com/a/63786673/5768908). – Gerardo Furtado Sep 08 '20 at 03:34
  • Yeah, I agree it is clearer with separate lines. However it's still good to mention comma, I almost forgot this possibility. – testing_22 Sep 08 '20 at 03:55
  • Thank you people for sharing those links. It's being really helpful – testing_22 Sep 08 '20 at 03:56

3 Answers3

3

alert() returns undefined, which is false-y. Therefore, window.confirm() will still run, for your example of ||.

As for a single pipe character |, that's a bitwise-OR, which you can read about here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Bitwise

Brad
  • 146,404
  • 44
  • 300
  • 476
  • Thank u for linking | meaning. Btw, if undefined is false why it still runs just the first member in alert() && alert() for example? Shouldn't it be like 0 && 0 -> 0? – testing_22 Sep 08 '20 at 04:01
  • @testing_22 The functions used the logical expression are still evaluated. That is, if you have `fn1() && fn2()`, both functions `fn1` and `fn2` have to be executed. Suppose they both return `false`, it's then like `false && false`, which of course evaluates to `false`. For the case of `fn1() || fn2()`, there is the concept of "short circuit". It's a bit of an optimization. JavaScript knows that if either side of the OR `||` operator is truthy, the expression evaluates to `true`. Therefore, if `fn1()` returns true, it can stop there and immediately evaluate as `true`. `fn2()` is not executed. – Brad Sep 08 '20 at 04:04
  • 1
    _“If `undefined` is \[falsy,\] why it still runs just the first member in `alert() && alert()`”_ — how else would you determine `alert() === undefined`? Logical conjunctions and disjunctions evaluate their operands from left to right, until a disjunction hits a truthy value or until a conjunction hits a falsy value. That value is then returned. If they don’t hit such a value, the _last_ operand is returned. _“if you have `fn1() && fn2()`, both functions `fn1` and `fn2` have to be executed”_ — If `fn1` returns a falsy value, `fn2` is _not_ executed. Similar short-circuit evaluation is applied. – Sebastian Simon Sep 08 '20 at 21:10
  • @user4642212 is correct... sorry, I should have been more clear, in my head for the `&&` example, `fn1` and `fn2` were returning `true`. :-) – Brad Sep 08 '20 at 21:31
3

A semicolon indicates the end of a statement.

If you aren't already aware, an expression is something which evaluates to a value. For example, 5, 'foobar', and myFn() are all expressions, because they evaluate to values.

Statements can be composed of multiple expressions. For example, const result = fn('foo') passes the 'foo' expression into the function call, and the function call returns a value which is assigned to result.

In your code, both lines are composed of two expressions, but each line happens to be a single statement. With this line:

alert() || window.confirm()

will first evaluate alert. Since alert returns undefined, the || operator then evaluates the expression on the right, which is window.confirm().

You can put multiple expressions together on the same by using operators like |, ||, or =. You can also evaluate multiple expressions by putting each as a separate statement, like

alert();
window.confirm();

Both will result in an alert box and a confirm dialog coming up.

CertainPerformance
  • 260,466
  • 31
  • 181
  • 209
  • The statement _“You can put multiple expressions together on the same by using operators like `|`, `||`, or `=`”_ is potentially confusing. You can’t put a function call anywhere in a chain of `=` operators, except at the end. Also, the comma operator could be mentioned here. – Sebastian Simon Sep 08 '20 at 03:27
  • Function calls can be put onto the right of an `=` like in the example `const result = fn('foo')`, I wasn't trying to exhaustively describe the possible syntax, just to give an example – CertainPerformance Sep 08 '20 at 03:28
  • And what about && instead? Why it just evaluates the first one? – testing_22 Sep 08 '20 at 04:00
  • @testing_22 `||` will short-circuit (not evaluate the second expression) if the first is truthy: `1 || 4` results in `1` without considering `4`. Similarly, `&&` will short-circuit if the first is falsey: `false && 5` results in `5` without considering `5`. Similarly, `false && foo()` doesn't invoke `foo`, and `alert() && window.confirm()` doesn't invoke `confirm`. – CertainPerformance Sep 08 '20 at 04:02
  • @testing_22 Please see [Does JavaScript have “Short-circuit” evaluation?](https://stackoverflow.com/q/12554578/4642212) and [MDN falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy). – Sebastian Simon Sep 08 '20 at 04:03
1

The || is an operator, like + or /; it calculates something. In the case of ||, it calculates whether one OR the other value is true.

Normally, you'd use that in something like an if statement: if (i===0 || j===0) {...} but it's not restricted to that; for instance, you could put the result in a variable, then use it in an if statement later: have_zero = i===0 || j===0; ...; if (have_zero) {...}

The || (and &&) operators do have one special thing: if the left side determines the answer, they don't bother calculating the right side (called "short-circuit evaluation").

Here, you're calculating alert() || window.confirm(), so it calls alert(); as others have noted, this returns undefined which doesn't determine the answer to the ||, so Javascript then calls window.confirm(). The answer is then thrown away, because you're not putting it in a variable or otherwise using it, but that's OK - you wanted to call the methods, you weren't interested in the answer.

sabik
  • 3,694
  • 1
  • 13
  • 14
  • Yeah, I used it by accident and it surprisingly worked. Now what I can't understand is why alert() && alert() just pop up one alert when alert() || alert() pop up two, since both were supposed to be undefined. – testing_22 Sep 08 '20 at 03:59
  • As others pointed out, `undefined` counts as false for the purposes of `||` and `&&`; as soon as `&&` gets one false result, it doesn't need to check the other value, because the overall answer will be false in any case. – sabik Sep 08 '20 at 06:39