I understand how short-circuit evaluation works when using the logical or operator in JavaScript, but I've run into what seems to be a weird edge case I don't fully understand.
So, this snippet works the way I would expect:
const a = 'a' || 'b';
with a having a value of 'a'.
And of course, this also works the way I would expect:
const a = false || 'b';
with a having a value of 'b'.
However, I've run into this weird situation with an expression like this:
const a = true || true || true ? 'a' : 'b';
where a now has a value of 'a'. I've tried other combinations, such as:
const a = true || false || true ? 'a' : 'b';
and a still has a value of 'a'.
Another thing to try is something like this:
const fn = () => true ? 'a' : 'b';
const a = true || fn();
and of course a has a value of true, and fn is never called.
What's going on here?
A logical OR || is evaluated from left to right and the first value that evaluates to a truthy value is returned, or the last one if none of them evaluates to true.
In this case, the first true trivially evaluates to true, thus the whole condition returns true:
true || true || false
As a result, the first expression of the ternary operator is evaluated, in this case 'a':
const a = true || true || true ? 'a' : 'b';
For this reason, a equals 'a'.
The same logic applies to the other cases you listed.
Related
From this question: What does "var FOO = FOO || {}" (assign a variable or an empty object to that variable) mean in Javascript?
I've learned that var FOO = FOO || {} essentially means "If FOO exists, then leave it untouched, else make it an empty object".
But how?
This is how I would parse this syntax:
var FOO = (FOO || {})
So: If FOO exists AND evaluates to Boolean value of True, then (FOO || {}) will return True, so eventually FOO will be completely overwritten and will hold the Boolean value of True from now on.
Else (FOO || {}) will return to whatever Boolean value {} evalueates to. Since an empty object, which {} is, always evaluates to True...
Then in ANY case (FOO || {}) should evaluate to True, so...
In ANY POSSIBLE CASE, after evaluating var FOO = FOO || {}, FOO should hold the trivial Boolean value of True, regardless of whatever it was holding before. Essentially, to my understanding, var FOO = FOO || {} should be equivalent to var FOO = True.
Where is my mistake?
If FOO exists AND evaluates to Boolean value of True, then (FOO || {}) will return True
That isn't how the || operator works in JS.
A correct interpretation is:
If the left hand side is a true value, evaluate as the left hand side (i.e. FOO), otherwise evaluate as the right hand side (i.e. {}).
var zero = 0;
var one = 1;
var two = 2;
console.log(zero || two);
console.log(one || two);
So: If FOO exists AND evaluates to Boolean value of True, then (FOO || {}) will return True, so eventually FOO will be completely overwritten and will hold the Boolean value of True from now on.
That is wrong, but the below lines surprise you if your background is Strictly Typed Languages :)
The expression doesn't return a boolean value. It returns the expression that can be evaluated to true.
Here is the docs for the same
Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.
Logical operators are typically used with Boolean (logical) values. When they are, they return a Boolean value. However, the && and || operators actually return the value of one of the specified operands, so if these operators are used with non-Boolean values, they may return a non-Boolean value.
Different examples given in docs might help you understand the above words.
o4 = false || (3 == 4) // f || f returns false
o5 = 'Cat' || 'Dog' // t || t returns "Cat"
o6 = false || 'Cat' // f || t returns "Cat"
o7 = 'Cat' || false // t || f returns "Cat"
o8 = '' || false // returns false
JavaScript || operator returns the expression itself not the boolean value. Here's a reference from Mozilla documentation
Returns expr1 if it can be converted to true; otherwise, returns
expr2. Thus, when used with Boolean values, || returns true if either
operand is true.
Reference :
Conversion to True in boolean depends on whether the expression evaluates to a Truthy value.
So: If FOO exists AND evaluates to Boolean value of True, then (FOO ||
{}) will return True
The problem of the concept is the cast. Here the Object is not cast to Boolean, JS leave it untouched.
So, If FOO is defined (FOO || {}) will return FOO and if is not defined will return {}
This is because of Short Circuit Evaluation.
Short-circuit evaluation says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND (&&) function evaluates to false, the overall value must be false; and when the first argument of the OR (||) function evaluates to true, the overall value must be true.
But if the first argument of AND function evaluates to true, the second argument has to be executed or evaluated to determine the value of expression; and when the first argument of OR function evaluates to false, the second argument has to be executed or evaluated to determine the value of the expression.
In-case of FOO || {};
This returns FOO if FOO evaluates to TRUE, because there is no need to evaluate second argument if first one is true.
This returns {} if FOO evaluates to FALSE, because the second argument need to be evaluated to get the value of the expression.
See here for more details..
I just noticed a weird behaviour. I am sure not the first to notice it but I would like to understand what is going on.
Why does true || true ? 'foo' : 'bar' resolves to 'foo'
And what makes it different from true || (true ? 'foo' : 'bar') that resolves to true?
jsFiddle: http://jsfiddle.net/tgdx5u8s/
The key difference is that without the parentheses, || has precedence over ?:. In more detail:
First case
true || true ? 'foo' : 'bar'
due to || having precedence over ?: is equivalent to:
(true || true) ? 'foo' : bar'
The || operator returns the left operand if it is is truthy, which in this case it is (otherwise it would return the right operand).
So this resolves to:
true ? 'foo' : 'bar'
which resolves to 'foo'.
Second case
true || (true ? 'foo' : 'bar')
resolves to:
true || 'foo'
Again the || operator returns the left operand if it is is truthy, which in this case it is. So this resolves to true.
... || ... binds tighter than ... ? ... : ..., so your statement is parsed as:
(true || true) ? 'foo' : 'bar'
true || true is true, so you get 'foo'.
About the first one
true || true ? 'foo' : 'bar'
Would be the same as:
(true || true) ? 'foo' : 'bar'
So essentially:
true ? 'foo' : 'bar'
About the second one
true || (true ? 'foo' : 'bar');
Would be the same as:
true || 'foo';
So true or whatever other thing is true (no need to even evaluate 'foo' for that one...)
This is because of order of operation. Usually || is handled before ?: but when you add the braces then the expression inside the braces is evaluated before ||.
So the first ends up true ? 'foo' : 'bar' and the second ends up as true || 'foo'
Can find order at: https://msdn.microsoft.com/en-us/library/aa691323(v=vs.71).aspx
Not that I want to go against the majority but the precedence of || is not the reason for the observed behavior but the precedence of the parentheses. The construct logical or expression '?' expression ':' conditional expression is not much more than a slightly restricted IF '(' expression ')' statement ELSE statement once-along time ago, when memory was measured in kilobytes, the difference between a fully optimizing compiler run and one without was measured in hours and the monitors had 50 rows with 80 characters if you were lucky-implemented to make things simpler and smaller for the computer and the compiler. Not the user.
So if you use the ?:; you don't need no if, no parentheses around the expression after the if, and no curly brackets if you have more than one line after the if. The lack of need of parentheses is, in my humble experience, the reason for most, well, let's call them irritations.
To translate your problem into something more readable:
var a;
if(true || true){
a = 'foo';
} else {
a = 'bar';
}
The second one throws an error because of its incorrect syntax instead of letting you scratch your head:
var a;
if(true || if(true){a='foo';}else{a='bar';})/*noop*/;
The advantage of the ?:; construct is its ability to fill the right side of a declaration. The first example can be easily reduced to:
a = true || true ? 'foo' : 'bar';
I find it more readable if you add the parentheses despite being redundant:
a = (true || true) ? 'foo' : 'bar';
But that's probably more a matter of personal taste.
I am debugging some JavaScript and can't explain what this || does:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
Why is this guy using var title = title || 'ERROR'? I sometimes see it without a var declaration as well.
What is the double pipe operator (||)?
The double pipe operator (||) is the logical OR operator . In most languages it works the following way:
If the first value is false, it checks the second value. If that's true, it returns true and if the second value is false, it returns false.
If the first value is true, it always returns true, no matter what the second value is.
So basically it works like this function:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
If you still don't understand, look at this table:
| true false
------+---------------
true | true true
false | true false
In other words, it's only false when both values are false.
How is it different in JavaScript?
JavaScript is a bit different, because it's a loosely typed language. In this case it means that you can use || operator with values that are not booleans. Though it makes no sense, you can use this operator with for example a function and an object:
(function(){}) || {}
What happens there?
If values are not boolean, JavaScript makes implicit conversion to boolean. It means that if the value is falsey (e.g. 0, "", null, undefined (see also All falsey values in JavaScript)), it will be treated as false; otherwise it's treated as true.
So the above example should give true, because empty function is truthy. Well, it doesn't. It returns the empty function. That's because JavaScript's || operator doesn't work as I wrote at the beginning. It works the following way:
If the first value is falsey, it returns the second value.
If the first value is truthy, it returns the first value.
Surprised? Actually, it's "compatible" with the traditional || operator. It could be written as following function:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
If you pass a truthy value as x, it returns x, that is, a truthy value. So if you use it later in if clause:
(function(x, y) {
var eitherXorY = x || y;
if (eitherXorY) {
console.log("Either x or y is truthy.");
} else {
console.log("Neither x nor y is truthy");
}
}(true/*, undefined*/));
you get "Either x or y is truthy.".
If x was falsey, eitherXorY would be y. In this case you would get the "Either x or y is truthy." if y was truthy; otherwise you'd get "Neither x nor y is truthy".
The actual question
Now, when you know how || operator works, you can probably make out by yourself what does x = x || y mean. If x is truthy, x is assigned to x, so actually nothing happens; otherwise y is assigned to x. It is commonly used to define default parameters in functions. However, it is often considered a bad programming practice, because it prevents you from passing a falsey value (which is not necessarily undefined or null) as a parameter. Consider following example:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
It looks valid at the first sight. However, what would happen if you passed false as flagA parameter (since it's boolean, i.e. can be true or false)? It would become true. In this example, there is no way to set flagA to false.
It would be a better idea to explicitly check whether flagA is undefined, like that:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Though it's longer, it always works and it's easier to understand.
You can also use the ES6 syntax for default function parameters, but note that it doesn't work in older browsers (like IE). If you want to support these browsers, you should transpile your code with Babel.
See also Logical Operators on MDN.
It means the title argument is optional. So if you call the method with no arguments it will use a default value of "Error".
It's shorthand for writing:
if (!title) {
title = "Error";
}
This kind of shorthand trick with boolean expressions is common in Perl too. With the expression:
a OR b
it evaluates to true if either a or b is true. So if a is true you don't need to check b at all. This is called short-circuit boolean evaluation so:
var title = title || "Error";
basically checks if title evaluates to false. If it does, it "returns" "Error", otherwise it returns title.
If title is not set, use 'ERROR' as default value.
More generic:
var foobar = foo || default;
Reads: Set foobar to foo or default.
You could even chain this up many times:
var foobar = foo || bar || something || 42;
Explaining this a little more...
The || operator is the logical-or operator. The result is true if the first part is true and it is true if the second part is true and it is true if both parts are true. For clarity, here it is in a table:
X | Y | X || Y
---+---+--------
F | F | F
---+---+--------
F | T | T
---+---+--------
T | F | T
---+---+--------
T | T | T
---+---+--------
Now notice something here? If X is true, the result is always true. So if we know that X is true we don't have to check Y at all. Many languages thus implement "short circuit" evaluators for logical-or (and logical-and coming from the other direction). They check the first element and if that's true they don't bother checking the second at all. The result (in logical terms) is the same, but in terms of execution there's potentially a huge difference if the second element is expensive to calculate.
So what does this have to do with your example?
var title = title || 'Error';
Let's look at that. The title element is passed in to your function. In JavaScript if you don't pass in a parameter, it defaults to a null value. Also in JavaScript if your variable is a null value it is considered to be false by the logical operators. So if this function is called with a title given, it is a non-false value and thus assigned to the local variable. If, however, it is not given a value, it is a null value and thus false. The logical-or operator then evaluates the second expression and returns 'Error' instead. So now the local variable is given the value 'Error'.
This works because of the implementation of logical expressions in JavaScript. It doesn't return a proper boolean value (true or false) but instead returns the value it was given under some rules as to what's considered equivalent to true and what's considered equivalent to false. Look up your JavaScript reference to learn what JavaScript considers to be true or false in boolean contexts.
|| is the boolean OR operator. As in JavaScript, undefined, null, 0, false are considered as falsy values.
It simply means
true || true = true
false || true = true
true || false = true
false || false = false
undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Basically, it checks if the value before the || evaluates to true. If yes, it takes this value, and if not, it takes the value after the ||.
Values for which it will take the value after the || (as far as I remember):
undefined
false
0
'' (Null or Null string)
Whilst Cletus' answer is correct, I feel more detail should be added in regards to "evaluates to false" in JavaScript.
var title = title || 'Error';
var msg = msg || 'Error on Request';
Is not just checking if title/msg has been provided, but also if either of them are falsy. i.e. one of the following:
false.
0 (zero)
"" (empty string)
null.
undefined.
NaN (a special Number value meaning Not-a-Number!)
So in the line
var title = title || 'Error';
If title is truthy (i.e., not falsy, so title = "titleMessage" etc.) then the Boolean OR (||) operator has found one 'true' value, which means it evaluates to true, so it short-circuits and returns the true value (title).
If title is falsy (i.e. one of the list above), then the Boolean OR (||) operator has found a 'false' value, and now needs to evaluate the other part of the operator, 'Error', which evaluates to true, and is hence returned.
It would also seem (after some quick firebug console experimentation) if both sides of the operator evaluate to false, it returns the second 'falsy' operator.
i.e.
return ("" || undefined)
returns undefined, this is probably to allow you to use the behavior asked about in this question when trying to default title/message to "". i.e. after running
var foo = undefined
foo = foo || ""
foo would be set to ""
Double pipe stands for logical "OR". This is not really the case when the "parameter not set", since strictly in JavaScript if you have code like this:
function foo(par) {
}
Then calls
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
are not equivalent.
Double pipe (||) will cast the first argument to Boolean and if the resulting Boolean is true - do the assignment, otherwise it will assign the right part.
This matters if you check for unset parameter.
Let's say, we have a function setSalary that has one optional parameter. If the user does not supply the parameter then the default value of 10 should be used.
If you do the check like this:
function setSalary(dollars) {
salary = dollars || 10
}
This will give an unexpected result for a call like:
setSalary(0)
It will still set the 10 following the flow described above.
Double pipe operator
This example may be useful:
var section = document.getElementById('special');
if(!section){
section = document.getElementById('main');
}
It can also be:
var section = document.getElementById('special') || document.getElementById('main');
To add some explanation to all said before me, I should give you some examples to understand logical concepts.
var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true
It means if the left side evaluated as a true statement it will be finished and the left side will be returned and assigned to the variable. in other cases the right side will be returned and assigned.
And operator have the opposite structure like below.
var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
Quote: "What does the construct x = x || y mean?"
Assigning a default value.
This means providing a default value of y to x,
in case x is still waiting for its value but hasn't received it yet or was deliberately omitted in order to fall back to a default.
And I have to add one more thing: This bit of shorthand is an abomination. It misuses an accidental interpreter optimization (not bothering with the second operation if the first is truthy) to control an assignment. That use has nothing to do with the purpose of the operator. I do not believe it should ever be used.
I prefer the ternary operator for initialization, for example,
var title = title?title:'Error';
This uses a one-line conditional operation for its correct purpose. It still plays unsightly games with truthiness but, that's JavaScript for you.
If co.chkShowRSB is false, what is the expected result? I would expect it to be false, but is this the way it works? And why?
var test = chkShow:co.chkShowRSB || true;
It's true in your case, as true is the second operand of || (so-called 'short-circuit or') operator. The common rule is...
var x = a || b; // = a (and b won't be evaluated), if it's a truthy value, b otherwise
var y = a && b; // = a (and b won't be evaluated), if it's a falsy value, b otherwise.
false || true
is true. There is no case where a boolean term with "or true" can be false.
Ok, so you got the picture by now x = false || true; assigns true. Why? It's quite easy knowing the use of the short-circuit-operator is the same as doing:
x = (false ? false : true);
However, it's mostly used to set default values for function arguments, so I'm guessing you're assuming x to be assigned the second operand if the first is undefined. There is no way to filter out undefined values exclusively except for explicitly checking for them. You should then use:
x = val === undefined ? defaultVal : val;
Or, because undefined needn't be undefined, and you want to be absolutely sure:
x = (function(val,undefined)//second argument will be the true undefined value
{
return (val === undefined ? defaultVal : val);
})(val);//don't pass second argument
you should use tertiary operator. your code will always return true if chkShow:co.chkShowRSB is boolean;
var test = chkShow:co.chkShowRSB == false ? false : true;
can someone explain me why my code isn't working as I want to?
test = function(argument){
var arg = argument || true;
console.log(arg)
};
test(false);
and return is always true. I thought that it will only be true if argument is 'undefined'?
thanks for answers! :)
|| is the logical or operator. So false OR true evaluates to true.
undefined is falsey as well, so its a short hand for returning the right-hand side of the operator.
You might want this instead
var arg = typeof argument !== 'undefined' ? argument : true;
It will print true if the argument is falsy, i.e.:
false
null
undefined
empty string
number 0
number NaN
e.g.:
'' || true
will evaluate to true.
change it to:
var arg=(typeof argument!=='undefined'?argument:true);
var test = function(argument){
var arg = typeof argument === "undefined" ? true : argument;
console.log(arg);
};
According to ECMA-262 11.11, a logical OR statement returns the value of the first truethy expression or the value of the last expression if no previous expression is truethy.
Logically anything ORed with true is always a true.
lets see the truth table for A and B
A B A || B
T T T <-- one of them is true
T F T <-- one of them is true
F T T <-- one of them is true
F F F <-- only both false can create a false in an OR operation.