Related
I would like to know if JavaScript has "short-circuit" evaluation like && Operator in C#. If not, I would like to know if there is a workaround that makes sense to adopt.
Yes, JavaScript has "short-circuit" evaluation.
if (true == true || foo.foo){
// Passes, no errors because foo isn't defined.
}
Live DEMO
if (false && foo.foo){
// Passes, no errors because foo isn't defined.
}
Live DEMO
The answer is yes!
This answer goes into great detail on how short-circuiting works in JavaScript, with all the gotchas and also relevant themes such as operator precedence.
If you’re looking for a quick definition and already understand how short-circuiting works, I’d recommend checking other answers.
What we (thought we) knew so far:
First let’s inspect the behavior we are all familiar with, inside the if condition, where we use && to check whether the two expressions are true:
const expr1 = true;
const expr2 = true;
if (expr1 && expr2) {
console.log("bar");
}
Now, your first instinct is probably to say: “Ah yes, quite simple, the code executes the statement if both expr1 and expr2 are evaluated as true“.
Well, yes and no. You are technically correct, that is the behavior you described, but that’s not exactly how the code is evaluated and we’ll need to delve deeper in order to fully understand.
How exactly is the && and || interpreted?
It’s time to look “under the hood” of the javascript engine.
Let’s consider this practical example:
function sanitize(x) {
if (isNaN(x)) {
return NaN;
}
return x;
}
let userInput = 0xFF; // As an example.
const res = sanitize(userInput) && userInput + 5
console.log(res);
Well, the result is 260, but why?
In order to get the answer, we need to understand how the short-circuit evaluation works.
By the MDN definition, the && operator in expr1 && expr2 performs as follows:
Logical AND (&&) evaluates operands from left to right, returning immediately with the value of the first falsy operand it encounters; if all values are truthy, the value of the last operand is returned.
If a value can be converted to true, the value is so-called truthy.
If a value can be converted to false, the value is so-called falsy.
[…]
As each operand is converted to a boolean, if the result of one conversion is found to be false, the AND operator stops and returns the original value of that falsy operand; it does not evaluate any of the remaining operands.
Or, more simply, in an older revision of the documentation:
Operator
Syntax
Description
Logical AND (&&)
expr1 && expr2
If expr1 can be converted to true, returns expr2; else, returns expr1.
So this means, in our practical example, the const res is evaluated the following way:
Invoke expr1, which is sanitize(userInput), or sanitize(0xFF).
Run sanitize(0xFF): check isNaN(x), or isNaN(0xFF), (which results in false because 0xFF is a valid hexadecimal number literal for 255), return x which is 0xFF, or 255. If isNaN(x) was true, sanitize would’ve returned NaN.
The expr1 resulted in 255, a “truthy” value, so it’s time to evaluate expr2. If NaN was returned, it’d stop as NaN is falsy.
Since sanitize(userInput) is truthy (a non-zero, finite number), keep going and add 5 to userInput.
“Truthy” means that expression can be evaluated as true.
So here, we were able to avoid additional if blocks and further isNaN checks with a simple usage of the && operator.
How it really works:
By now, we should at least have a picture how the short-circuit operators work.
The operators that exhibit short-circuiting behavior are:
Logical AND (&&)
Logical OR (||)
Nullish coalescing operator (??)
Optional chaining (?.)
The universal rule goes:
a && b && … && z evaluates to the first falsy operand, or to the last operand if none is found to be falsy.
a || b || … || z evaluates to the first truthy operand, or to the last operand if none is found to be truthy.
a ?? b ?? … ?? z evaluates to the first operand which is neither null nor undefined, or to the last operand, otherwise.
a?.b?.…?.z accesses each property in the chain and evaluates to the value of the nested z property if all previous links of the chain evaluate to something that can be converted to an object (i.e. neither null nor undefined); otherwise it returns undefined, regardless of which nested property fails.
Here are some further examples for better comprehension:
function a() {
console.log("a");
return false;
}
function b() {
console.log("b");
return true;
}
if (a() && b()){
console.log("foobar");
}
// `a()` is evaluated as `false`; execution is stopped.
function a() {
console.log("a");
return false;
}
function b() {
console.log("b");
return true;
}
if (a() || b()){
console.log("foobar");
}
/*
** 1. `a()` is evaluated as `false`.
** 2. So it should evaluate `expr2`, which is `b()`.
** 3. `b()` is evaluated `true`.
** 4. The statement `console.log("foobar");` is executed.
*/
function a() {
console.log("a");
return null;
}
function b() {
console.log("b");
return false;
}
function c() {
console.log("c");
return true;
}
if (a() ?? b() ?? c()){
console.log("foobar");
}
/*
** 1. `a()` is evaluated as `null`.
** 2. So it should evaluate `expr2`, which is `b()`.
** 3. `b()` is evaluated as `false`; execution is stopped.
*/
const deeply = {
get nested(){
console.log("nested");
return {
get object(){
console.log("object");
return null;
}
};
}
};
if (deeply?.nested?.object?.but?.not?.that?.deep){
console.log("foobar");
}
/*
** 1. `deeply` is evaluated as an object.
** 2. `deeply?.nested` is evaluated as an object.
** 3. `deeply?.nested?.object` is evaluated as `null`.
** 4. `?.but?.not?.that?.deep` is essentially skipped over; the entire optional chain is evaluated as `undefined`; execution is stopped.
*/
One last pesky, but very important thing: Operator precedence
Nice, hopefully you’re getting the hang of it!
Last thing we need to know is a rule about operator precedence, that is: The && operator is always evaluated prior to the || operator.
Consider the following example:
function a() { console.log("a"); return true;}
function b() { console.log("b"); return false;}
function c() { console.log("c"); return false;}
console.log(a() || b() && c());
// "a" is logged; execution is stopped.
The expression a() || b() && c() will, perhaps confusingly to some, result in a().
The reason is quite simple, it’s just our eyesight that’s kind of deceiving us, because we’re used to reading left-to-right.
Let’s take the console.log() and what not out and focus purely on the evaluation:
true || false && false
&& having a higher precedence than || means that the operands closest to && are evaluated first — but after all operations with an even higher precedence already being evaluated.
Since there’re only && and || here, these are just false and false.
|| works the same way, including the rule that all operations with an even higher precedence should already be evaluated.
So first, we need to evaluate false && false, which is just false.
Then we evaluate true || false (with the resulting false), which is true.
The whole expression is equivalent to (true || (false && false)), which is (true || (false)), which is (true).
You can also try an alternative perspective: in the ECMAScript specification (which is what the JavaScript language is based on), the expression expr1 || expr2 follows a pattern called the LogicalORExpression.
Following its definition, in simple terms, both expr1 and expr2 are their own LogicalANDExpression.
If you wanted to evaluate something like true || false && false, you’d have to evaluate the LogicalORExpression: (true) || (false && false).
You know that (true) is just true, but you don’t immediately know what (false && false) is.
So then, you’d have to evaluate the LogicalANDExpression: (false) && (false).
And now you’re done, because (false) is just false.
Only once you know the result of evaluating each LogicalANDExpression, you can move on to evaluate the constituting LogicalORExpression.
This is exactly what is meant by && being evaluated before ||, or && having a higher precedence than ||.
(NB: These grammar rules kill two birds with one stone: they define the evaluation order (via recursive definitions) and the operator precedence (in this case: left to right, and && before ||).)
Well, that might seem pretty tricky, all because of a few weird rules and semantics.
But remember, you can always escape operator precedence with parentheses, also known as the grouping operator (…) — just like in math.
function a() { console.log("a"); return true; }
function b() { console.log("b"); return false; }
function c() { console.log("c"); return false; }
console.log((a() || b()) && c());
/*
** 1. The parenthesized part is evaluated first.
** 2. `a()` is evaluated as `true`, so `b()` is skipped
** 3. `c()` is evaluated as `false`, stops execution.
*/
And we have yet to talk about where to place the ?? operator in terms of precedence!
But don’t worry: since operator precedence rules between && and || and ?? would be too confusing and too complicated, it is actually not allowed to put them next to each other!
They can only appear together in the same expression if it’s very clear which one is evaluated first.
(a ?? b) && c // Clearly, `(a ?? b)` is evaluated first.
a ?? (b && c) // Clearly, `(b && c)` is evaluated first.
a ?? b && c // Unclear! Throws a SyntaxError.
The idea is that logical expressions are read left-to-right, and if the value of the left condition is enough to get the total value, the right condition will not be processed and evaluated. Some very simple examples:
function test() {
const caseNumber = document.querySelector('#sel').value;
const userChoice = () => confirm('Press OK or Cancel');
if (caseNumber === '1') {
console.log (1 === 1 || userChoice());
} else if (caseNumber === '2') {
console.log (1 === 2 && userChoice());
} else if (caseNumber === '3') {
console.log (1 === 2 || userChoice());
} else if (caseNumber === '4') {
console.log (1 === 1 && userChoice());
} else if (caseNumber === '5') {
console.log (userChoice() || 1 === 1);
} else if (caseNumber === '6') {
console.log (userChoice() && 1 === 2);
}
}
<label for="sel">Select a number of a test case and press "RUN!":</label>
<br><select id="sel">
<option value="">Unselected</option>
<option value="1">Case 1</option>
<option value="2">Case 2</option>
<option value="3">Case 3</option>
<option value="4">Case 4</option>
<option value="5">Case 5</option>
<option value="6">Case 6</option>
</select>
<button onclick="test()">RUN!</button>
The first two cases above will print to console results true and false respectively and you will not even see the modal window asking you to press "OK" or "Cancel", because the left condition is sufficient to define the total result.
On the contrary, with the cases 3–6, you will see the modal window asking for your choice, because the former two depend on the right part (that is your choice), and the latter two — regardless of the fact that the aggregate values of these expressions do not depend on your choice — because left conditions are read first. So, it is important to place conditions left-to-right based on which ones you want to be processed first.
I would like to know if JavaScript has "short-circuit" evaluation like && Operator in C#. If not, I would like to know if there is a workaround that makes sense to adopt.
Yes, JavaScript has "short-circuit" evaluation.
if (true == true || foo.foo){
// Passes, no errors because foo isn't defined.
}
Live DEMO
if (false && foo.foo){
// Passes, no errors because foo isn't defined.
}
Live DEMO
The answer is yes!
This answer goes into great detail on how short-circuiting works in JavaScript, with all the gotchas and also relevant themes such as operator precedence.
If you’re looking for a quick definition and already understand how short-circuiting works, I’d recommend checking other answers.
What we (thought we) knew so far:
First let’s inspect the behavior we are all familiar with, inside the if condition, where we use && to check whether the two expressions are true:
const expr1 = true;
const expr2 = true;
if (expr1 && expr2) {
console.log("bar");
}
Now, your first instinct is probably to say: “Ah yes, quite simple, the code executes the statement if both expr1 and expr2 are evaluated as true“.
Well, yes and no. You are technically correct, that is the behavior you described, but that’s not exactly how the code is evaluated and we’ll need to delve deeper in order to fully understand.
How exactly is the && and || interpreted?
It’s time to look “under the hood” of the javascript engine.
Let’s consider this practical example:
function sanitize(x) {
if (isNaN(x)) {
return NaN;
}
return x;
}
let userInput = 0xFF; // As an example.
const res = sanitize(userInput) && userInput + 5
console.log(res);
Well, the result is 260, but why?
In order to get the answer, we need to understand how the short-circuit evaluation works.
By the MDN definition, the && operator in expr1 && expr2 performs as follows:
Logical AND (&&) evaluates operands from left to right, returning immediately with the value of the first falsy operand it encounters; if all values are truthy, the value of the last operand is returned.
If a value can be converted to true, the value is so-called truthy.
If a value can be converted to false, the value is so-called falsy.
[…]
As each operand is converted to a boolean, if the result of one conversion is found to be false, the AND operator stops and returns the original value of that falsy operand; it does not evaluate any of the remaining operands.
Or, more simply, in an older revision of the documentation:
Operator
Syntax
Description
Logical AND (&&)
expr1 && expr2
If expr1 can be converted to true, returns expr2; else, returns expr1.
So this means, in our practical example, the const res is evaluated the following way:
Invoke expr1, which is sanitize(userInput), or sanitize(0xFF).
Run sanitize(0xFF): check isNaN(x), or isNaN(0xFF), (which results in false because 0xFF is a valid hexadecimal number literal for 255), return x which is 0xFF, or 255. If isNaN(x) was true, sanitize would’ve returned NaN.
The expr1 resulted in 255, a “truthy” value, so it’s time to evaluate expr2. If NaN was returned, it’d stop as NaN is falsy.
Since sanitize(userInput) is truthy (a non-zero, finite number), keep going and add 5 to userInput.
“Truthy” means that expression can be evaluated as true.
So here, we were able to avoid additional if blocks and further isNaN checks with a simple usage of the && operator.
How it really works:
By now, we should at least have a picture how the short-circuit operators work.
The operators that exhibit short-circuiting behavior are:
Logical AND (&&)
Logical OR (||)
Nullish coalescing operator (??)
Optional chaining (?.)
The universal rule goes:
a && b && … && z evaluates to the first falsy operand, or to the last operand if none is found to be falsy.
a || b || … || z evaluates to the first truthy operand, or to the last operand if none is found to be truthy.
a ?? b ?? … ?? z evaluates to the first operand which is neither null nor undefined, or to the last operand, otherwise.
a?.b?.…?.z accesses each property in the chain and evaluates to the value of the nested z property if all previous links of the chain evaluate to something that can be converted to an object (i.e. neither null nor undefined); otherwise it returns undefined, regardless of which nested property fails.
Here are some further examples for better comprehension:
function a() {
console.log("a");
return false;
}
function b() {
console.log("b");
return true;
}
if (a() && b()){
console.log("foobar");
}
// `a()` is evaluated as `false`; execution is stopped.
function a() {
console.log("a");
return false;
}
function b() {
console.log("b");
return true;
}
if (a() || b()){
console.log("foobar");
}
/*
** 1. `a()` is evaluated as `false`.
** 2. So it should evaluate `expr2`, which is `b()`.
** 3. `b()` is evaluated `true`.
** 4. The statement `console.log("foobar");` is executed.
*/
function a() {
console.log("a");
return null;
}
function b() {
console.log("b");
return false;
}
function c() {
console.log("c");
return true;
}
if (a() ?? b() ?? c()){
console.log("foobar");
}
/*
** 1. `a()` is evaluated as `null`.
** 2. So it should evaluate `expr2`, which is `b()`.
** 3. `b()` is evaluated as `false`; execution is stopped.
*/
const deeply = {
get nested(){
console.log("nested");
return {
get object(){
console.log("object");
return null;
}
};
}
};
if (deeply?.nested?.object?.but?.not?.that?.deep){
console.log("foobar");
}
/*
** 1. `deeply` is evaluated as an object.
** 2. `deeply?.nested` is evaluated as an object.
** 3. `deeply?.nested?.object` is evaluated as `null`.
** 4. `?.but?.not?.that?.deep` is essentially skipped over; the entire optional chain is evaluated as `undefined`; execution is stopped.
*/
One last pesky, but very important thing: Operator precedence
Nice, hopefully you’re getting the hang of it!
Last thing we need to know is a rule about operator precedence, that is: The && operator is always evaluated prior to the || operator.
Consider the following example:
function a() { console.log("a"); return true;}
function b() { console.log("b"); return false;}
function c() { console.log("c"); return false;}
console.log(a() || b() && c());
// "a" is logged; execution is stopped.
The expression a() || b() && c() will, perhaps confusingly to some, result in a().
The reason is quite simple, it’s just our eyesight that’s kind of deceiving us, because we’re used to reading left-to-right.
Let’s take the console.log() and what not out and focus purely on the evaluation:
true || false && false
&& having a higher precedence than || means that the operands closest to && are evaluated first — but after all operations with an even higher precedence already being evaluated.
Since there’re only && and || here, these are just false and false.
|| works the same way, including the rule that all operations with an even higher precedence should already be evaluated.
So first, we need to evaluate false && false, which is just false.
Then we evaluate true || false (with the resulting false), which is true.
The whole expression is equivalent to (true || (false && false)), which is (true || (false)), which is (true).
You can also try an alternative perspective: in the ECMAScript specification (which is what the JavaScript language is based on), the expression expr1 || expr2 follows a pattern called the LogicalORExpression.
Following its definition, in simple terms, both expr1 and expr2 are their own LogicalANDExpression.
If you wanted to evaluate something like true || false && false, you’d have to evaluate the LogicalORExpression: (true) || (false && false).
You know that (true) is just true, but you don’t immediately know what (false && false) is.
So then, you’d have to evaluate the LogicalANDExpression: (false) && (false).
And now you’re done, because (false) is just false.
Only once you know the result of evaluating each LogicalANDExpression, you can move on to evaluate the constituting LogicalORExpression.
This is exactly what is meant by && being evaluated before ||, or && having a higher precedence than ||.
(NB: These grammar rules kill two birds with one stone: they define the evaluation order (via recursive definitions) and the operator precedence (in this case: left to right, and && before ||).)
Well, that might seem pretty tricky, all because of a few weird rules and semantics.
But remember, you can always escape operator precedence with parentheses, also known as the grouping operator (…) — just like in math.
function a() { console.log("a"); return true; }
function b() { console.log("b"); return false; }
function c() { console.log("c"); return false; }
console.log((a() || b()) && c());
/*
** 1. The parenthesized part is evaluated first.
** 2. `a()` is evaluated as `true`, so `b()` is skipped
** 3. `c()` is evaluated as `false`, stops execution.
*/
And we have yet to talk about where to place the ?? operator in terms of precedence!
But don’t worry: since operator precedence rules between && and || and ?? would be too confusing and too complicated, it is actually not allowed to put them next to each other!
They can only appear together in the same expression if it’s very clear which one is evaluated first.
(a ?? b) && c // Clearly, `(a ?? b)` is evaluated first.
a ?? (b && c) // Clearly, `(b && c)` is evaluated first.
a ?? b && c // Unclear! Throws a SyntaxError.
The idea is that logical expressions are read left-to-right, and if the value of the left condition is enough to get the total value, the right condition will not be processed and evaluated. Some very simple examples:
function test() {
const caseNumber = document.querySelector('#sel').value;
const userChoice = () => confirm('Press OK or Cancel');
if (caseNumber === '1') {
console.log (1 === 1 || userChoice());
} else if (caseNumber === '2') {
console.log (1 === 2 && userChoice());
} else if (caseNumber === '3') {
console.log (1 === 2 || userChoice());
} else if (caseNumber === '4') {
console.log (1 === 1 && userChoice());
} else if (caseNumber === '5') {
console.log (userChoice() || 1 === 1);
} else if (caseNumber === '6') {
console.log (userChoice() && 1 === 2);
}
}
<label for="sel">Select a number of a test case and press "RUN!":</label>
<br><select id="sel">
<option value="">Unselected</option>
<option value="1">Case 1</option>
<option value="2">Case 2</option>
<option value="3">Case 3</option>
<option value="4">Case 4</option>
<option value="5">Case 5</option>
<option value="6">Case 6</option>
</select>
<button onclick="test()">RUN!</button>
The first two cases above will print to console results true and false respectively and you will not even see the modal window asking you to press "OK" or "Cancel", because the left condition is sufficient to define the total result.
On the contrary, with the cases 3–6, you will see the modal window asking for your choice, because the former two depend on the right part (that is your choice), and the latter two — regardless of the fact that the aggregate values of these expressions do not depend on your choice — because left conditions are read first. So, it is important to place conditions left-to-right based on which ones you want to be processed first.
I would like to know if JavaScript has "short-circuit" evaluation like && Operator in C#. If not, I would like to know if there is a workaround that makes sense to adopt.
Yes, JavaScript has "short-circuit" evaluation.
if (true == true || foo.foo){
// Passes, no errors because foo isn't defined.
}
Live DEMO
if (false && foo.foo){
// Passes, no errors because foo isn't defined.
}
Live DEMO
The answer is yes!
This answer goes into great detail on how short-circuiting works in JavaScript, with all the gotchas and also relevant themes such as operator precedence.
If you’re looking for a quick definition and already understand how short-circuiting works, I’d recommend checking other answers.
What we (thought we) knew so far:
First let’s inspect the behavior we are all familiar with, inside the if condition, where we use && to check whether the two expressions are true:
const expr1 = true;
const expr2 = true;
if (expr1 && expr2) {
console.log("bar");
}
Now, your first instinct is probably to say: “Ah yes, quite simple, the code executes the statement if both expr1 and expr2 are evaluated as true“.
Well, yes and no. You are technically correct, that is the behavior you described, but that’s not exactly how the code is evaluated and we’ll need to delve deeper in order to fully understand.
How exactly is the && and || interpreted?
It’s time to look “under the hood” of the javascript engine.
Let’s consider this practical example:
function sanitize(x) {
if (isNaN(x)) {
return NaN;
}
return x;
}
let userInput = 0xFF; // As an example.
const res = sanitize(userInput) && userInput + 5
console.log(res);
Well, the result is 260, but why?
In order to get the answer, we need to understand how the short-circuit evaluation works.
By the MDN definition, the && operator in expr1 && expr2 performs as follows:
Logical AND (&&) evaluates operands from left to right, returning immediately with the value of the first falsy operand it encounters; if all values are truthy, the value of the last operand is returned.
If a value can be converted to true, the value is so-called truthy.
If a value can be converted to false, the value is so-called falsy.
[…]
As each operand is converted to a boolean, if the result of one conversion is found to be false, the AND operator stops and returns the original value of that falsy operand; it does not evaluate any of the remaining operands.
Or, more simply, in an older revision of the documentation:
Operator
Syntax
Description
Logical AND (&&)
expr1 && expr2
If expr1 can be converted to true, returns expr2; else, returns expr1.
So this means, in our practical example, the const res is evaluated the following way:
Invoke expr1, which is sanitize(userInput), or sanitize(0xFF).
Run sanitize(0xFF): check isNaN(x), or isNaN(0xFF), (which results in false because 0xFF is a valid hexadecimal number literal for 255), return x which is 0xFF, or 255. If isNaN(x) was true, sanitize would’ve returned NaN.
The expr1 resulted in 255, a “truthy” value, so it’s time to evaluate expr2. If NaN was returned, it’d stop as NaN is falsy.
Since sanitize(userInput) is truthy (a non-zero, finite number), keep going and add 5 to userInput.
“Truthy” means that expression can be evaluated as true.
So here, we were able to avoid additional if blocks and further isNaN checks with a simple usage of the && operator.
How it really works:
By now, we should at least have a picture how the short-circuit operators work.
The operators that exhibit short-circuiting behavior are:
Logical AND (&&)
Logical OR (||)
Nullish coalescing operator (??)
Optional chaining (?.)
The universal rule goes:
a && b && … && z evaluates to the first falsy operand, or to the last operand if none is found to be falsy.
a || b || … || z evaluates to the first truthy operand, or to the last operand if none is found to be truthy.
a ?? b ?? … ?? z evaluates to the first operand which is neither null nor undefined, or to the last operand, otherwise.
a?.b?.…?.z accesses each property in the chain and evaluates to the value of the nested z property if all previous links of the chain evaluate to something that can be converted to an object (i.e. neither null nor undefined); otherwise it returns undefined, regardless of which nested property fails.
Here are some further examples for better comprehension:
function a() {
console.log("a");
return false;
}
function b() {
console.log("b");
return true;
}
if (a() && b()){
console.log("foobar");
}
// `a()` is evaluated as `false`; execution is stopped.
function a() {
console.log("a");
return false;
}
function b() {
console.log("b");
return true;
}
if (a() || b()){
console.log("foobar");
}
/*
** 1. `a()` is evaluated as `false`.
** 2. So it should evaluate `expr2`, which is `b()`.
** 3. `b()` is evaluated `true`.
** 4. The statement `console.log("foobar");` is executed.
*/
function a() {
console.log("a");
return null;
}
function b() {
console.log("b");
return false;
}
function c() {
console.log("c");
return true;
}
if (a() ?? b() ?? c()){
console.log("foobar");
}
/*
** 1. `a()` is evaluated as `null`.
** 2. So it should evaluate `expr2`, which is `b()`.
** 3. `b()` is evaluated as `false`; execution is stopped.
*/
const deeply = {
get nested(){
console.log("nested");
return {
get object(){
console.log("object");
return null;
}
};
}
};
if (deeply?.nested?.object?.but?.not?.that?.deep){
console.log("foobar");
}
/*
** 1. `deeply` is evaluated as an object.
** 2. `deeply?.nested` is evaluated as an object.
** 3. `deeply?.nested?.object` is evaluated as `null`.
** 4. `?.but?.not?.that?.deep` is essentially skipped over; the entire optional chain is evaluated as `undefined`; execution is stopped.
*/
One last pesky, but very important thing: Operator precedence
Nice, hopefully you’re getting the hang of it!
Last thing we need to know is a rule about operator precedence, that is: The && operator is always evaluated prior to the || operator.
Consider the following example:
function a() { console.log("a"); return true;}
function b() { console.log("b"); return false;}
function c() { console.log("c"); return false;}
console.log(a() || b() && c());
// "a" is logged; execution is stopped.
The expression a() || b() && c() will, perhaps confusingly to some, result in a().
The reason is quite simple, it’s just our eyesight that’s kind of deceiving us, because we’re used to reading left-to-right.
Let’s take the console.log() and what not out and focus purely on the evaluation:
true || false && false
&& having a higher precedence than || means that the operands closest to && are evaluated first — but after all operations with an even higher precedence already being evaluated.
Since there’re only && and || here, these are just false and false.
|| works the same way, including the rule that all operations with an even higher precedence should already be evaluated.
So first, we need to evaluate false && false, which is just false.
Then we evaluate true || false (with the resulting false), which is true.
The whole expression is equivalent to (true || (false && false)), which is (true || (false)), which is (true).
You can also try an alternative perspective: in the ECMAScript specification (which is what the JavaScript language is based on), the expression expr1 || expr2 follows a pattern called the LogicalORExpression.
Following its definition, in simple terms, both expr1 and expr2 are their own LogicalANDExpression.
If you wanted to evaluate something like true || false && false, you’d have to evaluate the LogicalORExpression: (true) || (false && false).
You know that (true) is just true, but you don’t immediately know what (false && false) is.
So then, you’d have to evaluate the LogicalANDExpression: (false) && (false).
And now you’re done, because (false) is just false.
Only once you know the result of evaluating each LogicalANDExpression, you can move on to evaluate the constituting LogicalORExpression.
This is exactly what is meant by && being evaluated before ||, or && having a higher precedence than ||.
(NB: These grammar rules kill two birds with one stone: they define the evaluation order (via recursive definitions) and the operator precedence (in this case: left to right, and && before ||).)
Well, that might seem pretty tricky, all because of a few weird rules and semantics.
But remember, you can always escape operator precedence with parentheses, also known as the grouping operator (…) — just like in math.
function a() { console.log("a"); return true; }
function b() { console.log("b"); return false; }
function c() { console.log("c"); return false; }
console.log((a() || b()) && c());
/*
** 1. The parenthesized part is evaluated first.
** 2. `a()` is evaluated as `true`, so `b()` is skipped
** 3. `c()` is evaluated as `false`, stops execution.
*/
And we have yet to talk about where to place the ?? operator in terms of precedence!
But don’t worry: since operator precedence rules between && and || and ?? would be too confusing and too complicated, it is actually not allowed to put them next to each other!
They can only appear together in the same expression if it’s very clear which one is evaluated first.
(a ?? b) && c // Clearly, `(a ?? b)` is evaluated first.
a ?? (b && c) // Clearly, `(b && c)` is evaluated first.
a ?? b && c // Unclear! Throws a SyntaxError.
The idea is that logical expressions are read left-to-right, and if the value of the left condition is enough to get the total value, the right condition will not be processed and evaluated. Some very simple examples:
function test() {
const caseNumber = document.querySelector('#sel').value;
const userChoice = () => confirm('Press OK or Cancel');
if (caseNumber === '1') {
console.log (1 === 1 || userChoice());
} else if (caseNumber === '2') {
console.log (1 === 2 && userChoice());
} else if (caseNumber === '3') {
console.log (1 === 2 || userChoice());
} else if (caseNumber === '4') {
console.log (1 === 1 && userChoice());
} else if (caseNumber === '5') {
console.log (userChoice() || 1 === 1);
} else if (caseNumber === '6') {
console.log (userChoice() && 1 === 2);
}
}
<label for="sel">Select a number of a test case and press "RUN!":</label>
<br><select id="sel">
<option value="">Unselected</option>
<option value="1">Case 1</option>
<option value="2">Case 2</option>
<option value="3">Case 3</option>
<option value="4">Case 4</option>
<option value="5">Case 5</option>
<option value="6">Case 6</option>
</select>
<button onclick="test()">RUN!</button>
The first two cases above will print to console results true and false respectively and you will not even see the modal window asking you to press "OK" or "Cancel", because the left condition is sufficient to define the total result.
On the contrary, with the cases 3–6, you will see the modal window asking for your choice, because the former two depend on the right part (that is your choice), and the latter two — regardless of the fact that the aggregate values of these expressions do not depend on your choice — because left conditions are read first. So, it is important to place conditions left-to-right based on which ones you want to be processed first.
I'm trying to understand how JavaScript's logical OR operator works and I am trying to recreate a code I read in a book but with my own twist to it but I keep getting a reference error when I try to run the code.
function add(a,b) {
b || b = 1;
return a+b;
}
My understanding is that if the left operand is false then the right operand is evaluated then the right operand's value is returned or used. With the code above, what I am trying to do is when the function is invoked and the second parameter is omitted, it would use a default value of 1 as the second value to the equation, but I keep getting a reference error that states invalid left hand assignment.
Probably you wanna achieve this:
b = b || 1;
Try b || (b = 1) instead. That's also exactly what CoffeeScript generates for its ||= operator.
The problem is with operator precedence. Assignment = has lower precedence than boolean or ||, therefore this
b || b = 1
is interpreted as
(b || b) = 1
which is invalid, because you cannot assign to an expression. To achieve what you want you have to tell JS you want || first and then =:
b || (b = 1)
but a more common way to express this would be
b = b || 1
In the context of your function this might not work as expected, since 0 is a valid integer value, and your code will treat it as false and substitute it with 1. So, the correct, although more verbose, way to write your function is
function add(a, b) {
b = (typeof b == "undefined") ? 1 : b;
return a + b;
}
How can I use an inline if statement in JavaScript? Is there an inline else statement too?
Something like this:
var a = 2;
var b = 3;
if(a < b) {
// do something
}
You don't necessarily need jQuery. JavaScript alone will do this.
var a = 2;
var b = 3;
var c = ((a < b) ? 'minor' : 'major');
The c variable will be minor if the value is true, and major if the value is false.
This is known as a Conditional (ternary) Operator.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Conditional_Operator
There is a ternary operator, like this:
var c = (a < b) ? "a is less than b" : "a is not less than b";
For writing if statement inline, the code inside of it should only be one statement:
if ( a < b ) // code to be executed without curly braces;
You can also approximate an if/else using only Logical Operators.
(a && b) || c
The above is roughly the same as saying:
a ? b : c
And of course, roughly the same as:
if ( a ) { b } else { c }
I say roughly because there is one difference with this approach, in that you have to know that the value of b will evaluate as true, otherwise you will always get c. Bascially you have to realise that the part that would appear if () { here } is now part of the condition that you place if ( here ) { }.
The above is possible due to JavaScripts behaviour of passing / returning one of the original values that formed the logical expression, which one depends on the type of operator. Certain other languages, like PHP, carry on the actual result of the operation i.e. true or false, meaning the result is always true or false; e.g:
14 && 0 /// results as 0, not false
14 || 0 /// results as 14, not true
1 && 2 && 3 && 4 /// results as 4, not true
true && '' /// results as ''
{} || '0' /// results as {}
One main benefit, compared with a normal if statement, is that the first two methods can operate on the righthand-side of an argument i.e. as part of an assignment.
d = (a && b) || c;
d = a ? b : c;
if `a == true` then `d = b` else `d = c`
The only way to achieve this with a standard if statement would be to duplicate the assigment:
if ( a ) { d = b } else { d = c }
You may ask why use just Logical Operators instead of the Ternary Operator, for simple cases you probably wouldn't, unless you wanted to make sure a and b were both true. You can also achieve more streamlined complex conditions with the Logical operators, which can get quite messy using nested ternary operations... then again if you want your code to be easily readable, neither are really that intuative.
In plain English, the syntax explained:
if(condition){
do_something_if_condition_is_met;
}
else{
do_something_else_if_condition_is_not_met;
}
Can be written as:
condition ? do_something_if_condition_is_met : do_something_else_if_condition_is_not_met;
If you just want an inline IF (without the ELSE), you can use the logical AND operator:
(a < b) && /*your code*/;
If you need an ELSE also, use the ternary operation that the other people suggested.
You could do like this in JavaScript:
a < b ? passed() : failed();
<div id="ABLAHALAHOO">8008</div>
<div id="WABOOLAWADO">1110</div>
parseInt( $( '#ABLAHALAHOO' ).text()) > parseInt( $( '#WABOOLAWADO ).text()) ? alert( 'Eat potato' ) : alert( 'You starve' );
I often need to run more code per condition, by using: ( , , ) multiple code elements can execute:
var a = 2;
var b = 3;
var c = 0;
( a < b ? ( alert('hi'), a=3, b=2, c=a*b ) : ( alert('by'), a=4, b=10, c=a/b ) );
FYI, you can compose conditional operators
var a = (truthy) ? 1 : (falsy) ? 2 : 3;
If your logic is sufficiently complex, then you might consider using an IIFE
var a = (function () {
if (truthy) return 1;
else if (falsy) return 2;
return 3;
})();
Of course, if you plan to use this logic more than once, then you aught to encapsulate it in a function to keep things nice and DRY.
inline if:
(('hypothesis') ? 'truthy conclusion' : 'falsey conclusion')
truthy conclusion: statements executed when hypothesis is true
falsey conclusion: statements executed when hypothesis is false
your example:
var c = ((a < b) ? 'a<b statements' : '!(a<b) statements');
You can use the Ternary operator which equates to a simple if, else.
Ternary operation which calls functions for both outcomes:
(a < b) ? DoSomething() : DoSomethingElse();
Ternary operation which calls a function for only one of the outcomes:
(a < b) ? DoSomething() : {}; or (a < b)?.DoSomething();
To add to this you can also use inline if condition with && and || operators.
Like this
var a = 2;
var b = 0;
var c = (a > b || b == 0)? "do something" : "do something else";
Inline if in JavaScript is simple and requires no braces:
if (a < b) doSomething()
Technically you can have an else in the same line, but it requires a semicolon:
if (a < b) doSomething(); else doSomethingElse()
The above examples may not be desired by your team's coding standards. The most important thing is that you follow conventions that work for your team. Personally, I prefer if statements over ternaries in many cases because I find them easier to read.
Isn't the question essentially: can I write the following?
if (foo)
console.log(bar)
else
console.log(foo + bar)
the answer is, yes, the above will translate.
however, be wary of doing the following
if (foo)
if (bar)
console.log(foo)
else
console.log(bar)
else
console.log(foobar)
be sure to wrap ambiguous code in braces as the above will throw an exception (and similar permutations will produce undesired behaviour.)
Simplify ternary operator
var locked = 1;
var canChange = locked != 1 ? true : false;
If the locked is 1, then the canChange variable is set to false, otherwise, it is set to true.
In this case, you can simplify it by using a Boolean expression as follows:
var locked = 1;
var canChange = locked != 1;
For multiple JavaScript ternary operators
The following example shows how to use two ternary operators in the same expression:
var speed = 90;
var message = speed >= 120 ? 'Too Fast' : (speed >= 80 ? 'Fast' : 'OK');
console.log(message);
It is a best practice to use the ternary operator when it makes the code easier to read. If the logic contains many if...else statements, you shouldn’t use the ternary operators.
(condition) ? expressionTrue : expressionFalse;
Example
int a=20, b=10;
if (a>b) {
cout << "a greater than b";
} else {
cout << "b greater than a";
}
You can simply write:
int a=20, b=10;
(a>b) ? cout << "a greater than b" : cout << "b greater than a";