What is the explanation for behavior of the "||" operator (logical OR), when using it with false and undefined on both sides in JavaScript?
1)
> false || undefined
undefined
2)
> undefined || false
false
The logical OR operator isn't commutative like +, *, etc. It returns the first expression which can be converted into true. (Source Mozilla Doc)
In false || undefined, false can't be converted to true by definition (since it's the opposite), so it returns the second operand (undefined)
In undefined || false, undefined is a value, but considered as false in Javascript, so the logical operator evaluate the second operand and returns false (because both operands are false).
According to Logical Operators in Mozilla Docs:
Logical OR (||)
expr1 || expr2
Returns 'expr1' if it can be converted to true; otherwise, returns 'expr2.
1) in case false || undefined: false(expr1) can not be converted to true, so undefined(expr2) is returned
2) in case undefined || false: undefined(expr1) can not be converted to true, so
false(expr2) is returned
This question is not related particularly to just false and undefined but, to any of the Falsy Values in Javascript. Note that there are a total of six falsy values in Javascript:
false.
0 (zero)
'' or "" (an empty string)
null
undefined
NaN
When you run the logical OR operation between two Falsy Values, say <left value> || <right value> in JS, it always returns the value on the right side of the OR operator. Reason being that the OR operator, as per its implementation in ECMAScript Engines, in general returns the left value if it can be coerced to true. But, if the value on the left side of the operator cannot be coerced to true, the right value is always returned no matter what the value on the right is, instead of getting coerced as one might expect.
Related
What are the values in JavaScript that are 'falsey', meaning that they evaluate as false in expressions like if(value), value ? and !value?
There are some discussions of the purpose of falsey values on Stack Overflow already, but no exhaustive complete answer listing what all the falsey values are.
I couldn't find any complete list on MDN JavaScript Reference, and I was surprised to find that the top results when looking for a complete, authoritative list of falsey values in JavaScript were blog articles, some of which had obvious omissions (for example, NaN), and none of which had a format like Stack Overflow's where comments or alternative answers could be added to point out quirks, surprises, omissions, mistakes or caveats. So, it seemed to make sense to make one.
Falsey values in JavaScript
false
Zero of Number type: 0 and also -0, 0.0, and hex form 0x0 (thanks RBT)
Zero of BigInt type: 0n and 0x0n (new in 2020, thanks GetMeARemoteJob)
"", '' and `` - strings of length 0
null
undefined
NaN
document.all (in HTML browsers only)
This is a weird one. document.all is a falsey object, with typeof as undefined. It was a Microsoft-proprietory function in IE before IE11, and was added to the HTML spec as a "willful violation of the JavaScript specification" so that sites written for IE wouldn't break on trying to access, for example, document.all.something; it's falsy because if (document.all) used to be a popular way to detect IE, before conditional comments. See Why is document.all falsy? for details
"Falsey" simply means that JavaScript's internal ToBoolean function returns false. ToBoolean underlies !value, value ? ... : ...; and if (value). Here's its official specification (2020 working draft) (the only changes since the very first ECMAscript specification in 1997 are the addition of ES6's Symbols, which are always truthy, and BigInt, mentioned above:
Argument type
Result
Undefined
Return false.
Null
Return false.
Boolean
Return argument.
Number
If argument is +0, -0, or NaN, return false; otherwise return true.
String
If argument is the empty String (its length is zero), return false; otherwise return true.
BigInt
If argument is 0n, return false; otherwise return true.
Symbol
Return true.
Object
Return true.
Comparisons with == (loose equality)
It's worth talking about falsy values' loose comparisons with ==, which uses ToNumber() and can cause some confusion due to the underlying differences. They effectively form three groups:
false, 0, -0, "", '' all match each other with ==
e.g. false == "", '' == 0 and therefore 4/2 - 2 == 'some string'.slice(11);
null, undefined match with ==
e.g. null == undefined but undefined != false
It's also worth mentioning that while typeof null returns 'object', null is not an object, this is a longstanding bug/quirk that was not fixed in order to maintain compatibility. It's not a true object, and objects are truthy (except for that "wilful violation" document.all when Javascript is implemented in HTML)
NaN doesn't match anything, with == or ===, not even itself
e.g. NaN != NaN, NaN !== NaN, NaN != false, NaN != null
With "strict equality" (===), there are no such groupings. Only false === false.
This is one of the reasons why many developers and many style guides (e.g. standardjs) prefer === and almost never use ==.
Truthy values that actually == false
"Truthy" simply means that JavaScript's internal ToBoolean function returns true. A quirk of Javascript to be aware of (and another good reason to prefer === over ==): it is possible for a value to be truthy (ToBoolean returns true), but also == false.
You might think if (value && value == false) alert('Huh?') is a logical impossibility that couldn't happen, but it will, for:
"0" and '0' - they're non-empty strings, which are truthy, but Javascript's == matches numbers with equivalent strings (e.g. 42 == "42"). Since 0 == false, if "0" == 0, "0" == false.
new Number(0) and new Boolean(false) - they're objects, which are truthy, but == sees their values, which == false.
0 .toExponential(); - an object with a numerical value equivalent to 0
Any similar constructions that give you a false-equaling value wrapped in a type that is truthy
[], [[]] and [0] (thanks cloudfeet for the JavaScript Equality Table link)
Some more truthy values
These are just a few values that some people might expect to be falsey, but are actually truthy.
-1 and all non-zero negative numbers
' ', " ", "false", 'null'... all non-empty strings, including strings that are just whitespace
Anything from typeof, which always returns a non-empty string, for example:
typeof null (returns a string 'object' due to a longstanding bug/quirk)
typeof undefined (returns a string 'undefined')
Any object (except that "wilful violation" document.all in browsers). Remember that null isn't really an object, despite typeof suggesting otherwise. Examples:
{}
[]
function(){} or () => {} (any function, including empty functions)
Error and any instance of Error
Any regular expression
Anything created with new (including new Number(0) and new Boolean(false))
Any Symbol
true, 1, "1" and [1] return true when compared to each other with ==.
Don't forget about the non-empty string "false" which evaluates to true
Just to add to #user568458's list of falsy values:
In addition to integer number 0, the decimal number 0.0, 0.00 or any such zeroish number is also a falsy value.
var myNum = 0.0;
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet prints I am a falsy value
Similarly hex representation of the number 0 is also a falsy value as shown in below code snippet:
var myNum = 0x0; //hex representation of 0
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet again prints I am a falsy value.
Addition to the topic, as of ES2020 we have a new value which is falsy, it's BigInt zero (0n):
0n == false // true
-0n == false // true
0n === false // false
-0n === false // false
So with this, we now have 7 "falsy" values in total (not including document.all as mentioned by user above since it's part of DOM and not JS).
I am unable to understand this.
Following is expression uses OR operator
var subCond1 = adj.getData('relationEnabled') == 'true' || adj.getData('unhideIfHidden') || adj.getData('hlFixed') == 'true';
I am expecting that since it is OR operation, it should return boolean true/false, but instead I get string 'false' as a result.
Can anyone explain this please?
Yup, that's just one of the features of || in JavaScript, and it's deliberate. It doesn't return a boolean (necessarily), it works like this: It evaluates the left-hand operand and if that operand is truthy, it returns it; otherwise, it evalutes and returns the right-hand operand.
So what's "truthy"? Anything that isn't "falsy". :-) The falsy values are 0, "", null, undefined, NaN, and of course, false. Anything else is truthy.
If you need a boolean, just !! the result:
var subCond1 = !!(adj.getData('relationEnabled') == 'true' || adj.getData('unhideIfHidden') || adj.getData('hlFixed') == 'true');
...but you frequently don't need to bother.
This behavior of || is really useful, particularly (I find) when dealing with object references that may be null, when you want to provide a default:
var obj = thisMayBeNull || {};
Now, obj will be thisMayBeNull if it's truthy (non-null object references are truthy), or {} if thisMayBeNull is falsy.
More in this article on my blog: JavaScript's Curiously-Powerful OR Operator (||)
Just to round things out: The && operator has a similar behavior: It evaluates the left-hand operand and, if it's falsy, returns it; otherwise it evaluates and returns the right-hand operator. This is useful if you want an object property from a variable which may be null:
var value = obj && obj.property;
value will be the value of obj if obj is falsy (for instance, null), or the value of obj.property if obj is truthy.
Javascript returns the first operand that has a truthy value, whatever that truthy value is or the value of the last operand if none before are truthy. That is a designed feature of Javascript (yes it is different than other languages).
You can turn that into a boolean by comparing to see if it is == true if you want or it is sometimes done with !!.
What are the values in JavaScript that are 'falsey', meaning that they evaluate as false in expressions like if(value), value ? and !value?
There are some discussions of the purpose of falsey values on Stack Overflow already, but no exhaustive complete answer listing what all the falsey values are.
I couldn't find any complete list on MDN JavaScript Reference, and I was surprised to find that the top results when looking for a complete, authoritative list of falsey values in JavaScript were blog articles, some of which had obvious omissions (for example, NaN), and none of which had a format like Stack Overflow's where comments or alternative answers could be added to point out quirks, surprises, omissions, mistakes or caveats. So, it seemed to make sense to make one.
Falsey values in JavaScript
false
Zero of Number type: 0 and also -0, 0.0, and hex form 0x0 (thanks RBT)
Zero of BigInt type: 0n and 0x0n (new in 2020, thanks GetMeARemoteJob)
"", '' and `` - strings of length 0
null
undefined
NaN
document.all (in HTML browsers only)
This is a weird one. document.all is a falsey object, with typeof as undefined. It was a Microsoft-proprietory function in IE before IE11, and was added to the HTML spec as a "willful violation of the JavaScript specification" so that sites written for IE wouldn't break on trying to access, for example, document.all.something; it's falsy because if (document.all) used to be a popular way to detect IE, before conditional comments. See Why is document.all falsy? for details
"Falsey" simply means that JavaScript's internal ToBoolean function returns false. ToBoolean underlies !value, value ? ... : ...; and if (value). Here's its official specification (2020 working draft) (the only changes since the very first ECMAscript specification in 1997 are the addition of ES6's Symbols, which are always truthy, and BigInt, mentioned above:
Argument type
Result
Undefined
Return false.
Null
Return false.
Boolean
Return argument.
Number
If argument is +0, -0, or NaN, return false; otherwise return true.
String
If argument is the empty String (its length is zero), return false; otherwise return true.
BigInt
If argument is 0n, return false; otherwise return true.
Symbol
Return true.
Object
Return true.
Comparisons with == (loose equality)
It's worth talking about falsy values' loose comparisons with ==, which uses ToNumber() and can cause some confusion due to the underlying differences. They effectively form three groups:
false, 0, -0, "", '' all match each other with ==
e.g. false == "", '' == 0 and therefore 4/2 - 2 == 'some string'.slice(11);
null, undefined match with ==
e.g. null == undefined but undefined != false
It's also worth mentioning that while typeof null returns 'object', null is not an object, this is a longstanding bug/quirk that was not fixed in order to maintain compatibility. It's not a true object, and objects are truthy (except for that "wilful violation" document.all when Javascript is implemented in HTML)
NaN doesn't match anything, with == or ===, not even itself
e.g. NaN != NaN, NaN !== NaN, NaN != false, NaN != null
With "strict equality" (===), there are no such groupings. Only false === false.
This is one of the reasons why many developers and many style guides (e.g. standardjs) prefer === and almost never use ==.
Truthy values that actually == false
"Truthy" simply means that JavaScript's internal ToBoolean function returns true. A quirk of Javascript to be aware of (and another good reason to prefer === over ==): it is possible for a value to be truthy (ToBoolean returns true), but also == false.
You might think if (value && value == false) alert('Huh?') is a logical impossibility that couldn't happen, but it will, for:
"0" and '0' - they're non-empty strings, which are truthy, but Javascript's == matches numbers with equivalent strings (e.g. 42 == "42"). Since 0 == false, if "0" == 0, "0" == false.
new Number(0) and new Boolean(false) - they're objects, which are truthy, but == sees their values, which == false.
0 .toExponential(); - an object with a numerical value equivalent to 0
Any similar constructions that give you a false-equaling value wrapped in a type that is truthy
[], [[]] and [0] (thanks cloudfeet for the JavaScript Equality Table link)
Some more truthy values
These are just a few values that some people might expect to be falsey, but are actually truthy.
-1 and all non-zero negative numbers
' ', " ", "false", 'null'... all non-empty strings, including strings that are just whitespace
Anything from typeof, which always returns a non-empty string, for example:
typeof null (returns a string 'object' due to a longstanding bug/quirk)
typeof undefined (returns a string 'undefined')
Any object (except that "wilful violation" document.all in browsers). Remember that null isn't really an object, despite typeof suggesting otherwise. Examples:
{}
[]
function(){} or () => {} (any function, including empty functions)
Error and any instance of Error
Any regular expression
Anything created with new (including new Number(0) and new Boolean(false))
Any Symbol
true, 1, "1" and [1] return true when compared to each other with ==.
Don't forget about the non-empty string "false" which evaluates to true
Just to add to #user568458's list of falsy values:
In addition to integer number 0, the decimal number 0.0, 0.00 or any such zeroish number is also a falsy value.
var myNum = 0.0;
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet prints I am a falsy value
Similarly hex representation of the number 0 is also a falsy value as shown in below code snippet:
var myNum = 0x0; //hex representation of 0
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet again prints I am a falsy value.
Addition to the topic, as of ES2020 we have a new value which is falsy, it's BigInt zero (0n):
0n == false // true
-0n == false // true
0n === false // false
-0n === false // false
So with this, we now have 7 "falsy" values in total (not including document.all as mentioned by user above since it's part of DOM and not JS).
I'm stuck with the following:
foo = properties[field] || overrides.default || config.widget.default || undefined;
with
console.log(properties[field]) // undefined
console.log(overrides.default) // 0
console.log(config.widget.default) // undefined
So as I understand, foo should be 0. Yet... it's undefined
This still works:
foo = properties[field] || overrides.default;
But as soon as I add another OR option, it does not work anymore.
Question:
Why is my 2nd operand with value=0 not overriding the undefined operands?
Thanks!
The || operator returns its left-hand operand if it is truthy, otherwise it returns the right-hand operand.
In your example, all operands have falsey values, so the compound || statement returns the right-most value.
In JS, the following are all falsey: 0, "" (empty string), undefined, null, NaN. And of course false. All other values are truthy (including strings like "0" or "false" because they're not empty strings).
Can someone please explain Why does Boolean(Infinity) is true but Boolean(NaN) is false?
Infinity || true
expression gives Infinity.
`
NaN || true
` expression gives true.
EMCAScript's logical OR casts its arguments to booleans using ToBoolean, which behaves as follows for numbers:
The result is false if the argument is +0, −0, or NaN; otherwise the result is true.
Thus, NaN becomes false, and Infinity becomes true. We sometimes refer to values as "truthy" or "falsy" depending on whether ToBoolean coerces them to true or false.
If you look at the spec for logical OR, the operator returns either the original lval or rval (left/right value), not its coerced boolean value. This is why (Infinity || true) == Infinity: the value of ToBoolean(lval) is true, so the expression returns the original lval.
This is a combination of two things: How "truthiness" is tested, and the curiously-powerful || operator.
Truthiness: When using boolean logic in JavaScript, the arguments are converted to booleans. How this happens is covered in the spec, Section 9.2, which says amongst other things that when converting a value to a boolean from a number:
The result is false if the argument is +0, −0, or NaN; otherwise the result is true.
Curiously-powerful || operator: JavaScript's || operator does not evalute to true or false. It evaluates to its left-hand argument if that argument is "truthy," or its right-hand argument otherwise. So 1 || 0 is 1, not true; and false || 0 is 0 (even though 0 is falsey). So for the same reason, Infinity || true is Infinity, not true.
This feature of || is incredibly powerful. You can do things like this, for instance:
someElement.innerHTML = name || "(name missing)";
...and if name is not undefined, null, 0, "", false, or NaN, innerHTML gets set to name; if it is one of those values, it gets set to "(name missing").
Similarly, you can have default objects:
var obj = someOptionalObject || {};
The uses are many and varied. You do have to be careful, though, that you don't unintentionally weed out valid falsey values like 0 when you're defaulting things in this way. :-)
A chain of || operators strung together (a || b || c) returns the first truthy argument in the chain, or the last argument if none of them are truthy.
The && operator does something quite similar: It returns its first argument if that argument is falsey, or its right argument otherwise. So 0 && 1 is 0, not false. 2 && 1 is 1, because 2 is not falsey. And chains of them return the first falsey arg, or the last arg, which is handy when you need to get a property from a nested object:
var prop = obj && obj.subobj && obj.subobj.property || defaultValue;
...returns obj if it's falsey, or obj.subobj if it's falsey, or obj.subobj.property if neither of the first two is falsey. Then the result of that || defaultValue gives you either the property, or the default.
It is because NaN stands for "not a number", practically speaking it has no value. In certain languages (like Java, AS3) this is the default value of an uninitialized floating point variable. However Infinity (no matter positive/negative) is a valid representation of an unreachable value.
When you convert their numeric value to boolean, it has come into effect.