Does JavaScript have Short-circuit evaluation?
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
Why does short-circuit evaluation work when operator precedence says it shouldn't?
Or am I confusing matters?
You are. I think it's much simpler to think about precedence as grouping than ordering. It affects the order of evaluation, but only because it changes the grouping.
I don't know about Javascript for sure, but in Java operands are always evaluated in left-to-right order. The fact that ==
has higher precedence than ||
just means that
true || foo == getValue()
is evaluated as
true || (foo == getValue())
rather than
(true || foo) == getValue()
If you just think about precedence in that way, and then consider that evaluation is always left-to-right (so the left operand of ||
is always evaluated before the right operand, for example) then everything's simple - and getValue()
is never evaluated due to short-circuiting.
To remove short-circuiting from the equation, consider this example instead:
A + B * C
... where A
, B
and C
could just be variables, or they could be other expressions such as method calls. In Java, this is guaranteed to be evaluated as:
- Evaluate
A
(and remember it for later) - Evaluate
B
- Evaluate
C
- Multiply the results of evaluating
B
andC
- Add the result of evaluating
A
with the result of the multiplication
Note how even though *
has higher precedence than +
, A
is still evaluated before either B
or C
. If you want to think of precedence in terms of ordering, note how the multiplication still happens before the addition - but it still fulfills the left-to-right evaluation order too.
Why does this short circuit evaluation return undefined if first value is false?
In your updated example, the logical AND … && …
has a higher order of precedence (5) than the evaluation of the ternary … ? … : …
(3).
Check out the table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table
using Short-Circuiting ( || ) in Object in JavaScript
The non-descriptive variable names don't really help to explain the situation. Let's start of by rewriting the code with more descriptive variable names.
const game = {
score: "4:0",
scored: ["Lewandowski", "Gnarby", "Lewandowski", "Hummels"],
};
const goals = {};
for (const player of game.scored) {
goals[player]++ || (goals[player] = 1);
}
console.log(goals);
goals[player]++
increments the goals
for player
by 1 and returns the old value. The tricky thing in goals[player]++
is that player
might not be present in goals
yet. In which case undefined
is returned (which is falsy). Because the value is falsy the second operand of the OR operator will be executed. (goals[player] = 1)
will set the goals
for player
to 1
.
The code is essentially counting how often a specific name is present in the game.scored
array. The presence of a name symbolises a goal made by them.
A less cryptic way of writing similar code would be:
const goals = {};
for (const player of game.scored) {
if (player in goals) {
goals[player] += 1; // add 1 to the current score
} else {
goals[player] = 1; // no score present so use 1
}
}
However I usually prefer to set a default value, this way you don't have to split the logic into two actions:
const goals = {};
for (const player of game.scored) {
goals[player] ||= 0; // assign 0 if the current value is falsy
goals[player] += 1; // add 1 to the current value
}
Note that ||=
is fairly new, if you write JavaScript for older browser you can use the following instead:
if (!goals[player]) goals[player] = 0;
Short circuit evaluation and assigning either true or false to a variable
You can use the nullish coalescing operator instead.
let finalConfig = preloadedConfig.configA ?? true;
Alternatively, you can use a hasOwnProperty
check.
let finalConfig = preloadedConfig.hasOwnProperty('configA') ? preloadedConfig.configA : true;
One-line short-circuit evaluation with && || in JavaScript
This one-liner is the equivalent of saying:
var prefix;
if(options && options.prefix){
prefix = options.prefix;
} else{
prefix = '';
}
Short-Circuit Evaluation of Logical Expressions in JavaScript
x is 5 which is binary 101, (x >>= 5) is therefore zero, x is assigned zero, and y++ in the first statement is not executed.
(x << 5) is likewise zero since x is now zero, so the y++ in the second statement also does not execute. The value of y remains 10, since no y++ is executed.
I don't know where your author is getting y == 11 from, it's wrong.
The IDE error is a red herring - it does not understand your file contains javascript (or you delimiited the javascript incorrectly) and is trying to parse it as XML / HTML.
Cleanest way to assign with short circuit evaluation on multiple conditions
You can chain ternary operators
shipToAddLine: addresses ? addresses[0].shipToAddLine : (cart ? cart.shipToAddLine : null),
Short circuit evaluation in JavaScript - SyntaxError: Unexpected token 'return'
The right hand side of &&
needs to be an expression. You're trying to put a statement there.
The &&
has to evaluate as something but return x
doesn't give you a value. It exits the function and passes its RHS to the calling function.
Related Topics
How to Get the Difference Between Two Dates in JavaScript
Best Way to Find If an Item Is in a JavaScript Array
How to Find the Operating System Details Using JavaScript
How to Handle Newlines in Json
Regex to Extract All Matches from String Using Regexp.Exec
How to Show a Running Progress Bar While Page Is Loading
Ellipsis in the Middle of a Text (MAC Style)
Sending Command Line Arguments to Npm Script
What Is the JavaScript ≫≫≫ Operator and How to Use It
Iterating Over Result of Getelementsbyclassname Using Array.Foreach
How to Chain and Share Prior Results With Promises
JavaScript and Operator Within Assignment
What Are Alternatives to Document.Write
Sleep in JavaScript - Delay Between Actions
Are JavaScript Strings Immutable? Do I Need a "String Builder" in JavaScript
Chained Promises Not Passing on Rejection