Why is this shift operation evaluating to true in JavaScript? [duplicate] - javascript

Can someone please explain JavaScript Truthy and Falsy, using the below sample data. I have read other threads but still confused.
var a = 0;
var a = 10 == 5;
var a = 1;
var a = -1;
From my understanding, I believe that var a = 1; is the only truthy and the rest are falsy - is this correct?

From my understanding, I believe that var a = 1; is the only truthy and the rest are falsy’s - is this correct?
No.
var a = 0;
Number zero is falsy. However, note that the string zero "0" is truthy.
var a = 10 == 5;
This is same as var a = (10 == 5);, so this is falsy.
var a = 1;
var a = -1;
Any non-zero number including negative numbers is truthy.
Quoting from MDN
In JavaScript, a truthy value is a value that translates to true when evaluated in a Boolean context. All values are truthy unless they are defined as falsy (i.e., except for false, 0, "", null, undefined, and NaN).
List of falsy values in JavaScript:From MDN
false
null
undefined
0
NaN
'', "", ``(Empty template string)
document.all
0n: BigInt
-0

There's a simple way to check, which you can use now and forever:
function truthyOrFalsy(a) {
return a ? "truthy" : "falsy";
}
To wit:
> truthyOrFalsy(0)
"falsy"
> truthyOrFalsy(10 == 5)
"falsy"
> truthyOrFalsy(1)
"truthy"
> truthyOrFalsy(-1)
"truthy"
Also see a list of all falsey values in JavaScript.

Truthy -> Value that resolve to true in boolean context
Falsy -> Value that resolve to false in boolean context
For better understanding, `falsy` values are given below.
false
0
empty string
null
undefined
NaN

FALSY
false
0 (zero)
"", '', `` (empty strings)
null
undefined
NaN (not a number)
note : Empty array ([]) is not falsy
TRUTHY
Everything that is not FALSY

The below answer might help someone.
As well as a type, each value also has an inherent Boolean value, generally known as either truthy or falsy. Some of the rules are a little bizarre, so understanding the concepts and effect on comparison helps when debugging JavaScript applications.
The following values are always falsy:
false
0 (zero)
-0 (minus zero)
0n (BigInt zero)
'', "", `` (empty string)
null
undefined
NaN
Everything else is truthy. That includes:
'0' (a string containing a single zero)
'false' (a string containing the text “false”)
[] (an empty array)
{} (an empty object)
function(){} (an “empty” function)
A single value can therefore be used within conditions. For example:
if (value) { // value is truthy } else { // value is falsy // it could be false, 0, '', null, undefined or NaN }

one more check version:
function truthyOrFalsy(a) {
return (a && "truthy") || "falsy";
}

In short there are only 6 types of falsy values:
You can use this snippet to test them:
function isTruthy(val){
if(val){
console.log(val + ' is Truthy');
}else{
console.log(val + ' is falsy');
}
}
// all below are truthy
isTruthy (true)
isTruthy ({})
isTruthy ([])
isTruthy (42)
isTruthy ("0")
isTruthy ("false")
isTruthy (new Date())
isTruthy (-42)
isTruthy (12n)
isTruthy (3.14)
isTruthy (-3.14)
isTruthy (Infinity)
isTruthy (-Infinity)
//all below are falsy
isTruthy(0);
isTruthy("");
isTruthy(false);
isTruthy(NaN);
isTruthy(null);
isTruthy(undefined);
Refer this site for details: https://developer.mozilla.org/en-US/docs/Glossary/Falsy

Easy way to check Falsy Value and True value
function truthyOrFalsy(val){
if(val){
console.log (`${val} is truthy`);
} else{
console.log (`${val} is falsy`);
}
}
Check all FALSY value:
truthyOrFalsy(false); //Output: false is falsy
truthyOrFalsy(null); //Output: null is falsy
truthyOrFalsy(0); //Output: 0 is falsy
truthyOrFalsy(''); //Output: is falsy [blank refers to '']
truthyOrFalsy(NaN); //Output: NaN is falsy
truthyOrFalsy(undefined); //Output: undefined is falsy
Please note that undefined is not explicitly used to set as value.
Some common scenarios will create undefined:
Parameter defined in function but not passed argument in callback function.
If nothing returns in function
If accessing to an object property/method which is not defined
If accessing to an array element which is not defined
function add(num1, num2){
console.log(num1, num2);
}
const result = add(44);
console.log(result);
//Output: 44 undefined
// undefined
const car = {color:"Blue", price: 200000};
console.log(car.category);
//Output: undefined
arrColors = ["Blue", "Sky", "Purple"];
console.log(arrColors[5]);
//Output: undefined
Check all TRUTHY values
All values are truthy unless they are defined as falsy.
Although ' ', '0', -1, [] could be enlisted to be checked.
truthyOrFalsy(' '); //Output: is truty [blank refers to space inside
// quote ]
truthyOrFalsy('0'); //Output: 0 is truty
truthyOrFalsy([]); //Output: is truty [blank refers to an empty array]
truthyOrFalsy(-1); //Output: -1 is truty

Another way to evaluate whether something is truthy or falsy that I like to use is
function truthyOrFalsy(a) {
return !!a;
}

Related

I don't understand the line below the prompt method of the while loop

let sum = 0;
while (true) {
let value = +prompt("Enter a number", '');
if (!value) break; // (*)
sum += value;
}
alert( 'Sum: ' + sum );
I don't understand the line below the prompt method. How does it work and what does if(!value)
refers to?
The ! used here is the Logical NOT operator. It evaluates any expression or value into a boolean. For truthy values, the ! operator returns false. For falsey values, it returns true. In JavaScript, 0, null, undefined, NaN, '' are all falsey values.
if(!value) would check whether the value is falsey. In case a falsey value is met, the loop will break.

Why ![] and [] == false yelds different results? [duplicate]

Empty arrays are true but they're also equal to false.
var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");
I guess this is due to the implicit conversion operated by the equality operator.
Can anyone explain what's going on behind the scenes?
You're testing different things here.
if (arr) called on object (Array is instance of Object in JS) will check if the object is present, and returns true/false.
When you call if (arr == false) you compare values of this object and the primitive false value. Internally, arr.toString() is called, which returns an empty string "".
This is because toString called on Array returns Array.join(), and empty string is one of falsy values in JavaScript.
Regarding the line:
if (arr == false) console.log("It's false!");
Maybe these will help:
console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true
What I believe is happening is that the boolean false is coerced to 0 for comparison with an object (the left-hand side). The object is coerced to a string (the empty string). Then, the empty string is coerced into a number, as well, namely zero. And so the final comparison is 0 == 0, which is true.
Edit: See this section of the spec for details on exactly how this works.
Here's what's happening, starting at rule #1:
1. If Type(x) is different from Type(y), go to step 14.
The next rule that applies is #19:
19. If Type(y) is Boolean, return the result of the comparison x ==
ToNumber(y).
The result of ToNumber(false) is 0, so we now have:
[] == 0
Again, rule #1 tells us to jump to step #14, but the next step that actually applies is #21:
21. If Type(x) is Object and Type(y) is either String or Number, return the
result of the comparison
ToPrimitive(x)== y.
The result of ToPrimitive([]) is the empty string, so we now have:
"" == 0
Again, rule #1 tells us to jump to step #14, but the next step that actually applies is #17:
17. If Type(x) is String and Type(y) is Number, return the result of the
comparison ToNumber(x)== y.
The result of ToNumber("") is 0, which leaves us with:
0 == 0
Now, both values have the same type, so the steps continue from #1 until #7, which says:
7. If x is the same number value as y, return true.
So, we return true.
In brief:
ToNumber(ToPrimitive([])) == ToNumber(false)
To supplement Wayne's answer and to try to explain why ToPrimitive([]) returns "", it's worth considering two possible types of answers to the 'why' question. The first type of answer is: "because the specification says this is how JavaScript will behave." In the ES5 spec, section 9.1, which describes the result of ToPrimitive as a default value for an Object:
The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType.
Section 8.12.8 describes the [[DefaultValue]] method. This method takes a "hint" as an argument, and the hint can be either String or Number. To simplify the matter by dispensing with some details, if the hint is String, then [[DefaultValue]] returns the value of toString() if it exists and returns a primitive value and otherwise returns the value of valueOf(). If the hint is Number, the priorities of toString() and valueOf() are reversed so that valueOf() is called first and its value returned if it's a primitive. Thus, whether [[DefaultValue]] returns the result of toString() or valueOf() depends on the specified PreferredType for the object and whether or not these functions return primitive values.
The default valueOf() Object method just returns the object itself, which means that unless a class overrides the default method, valueOf() just returns the Object itself. This is the case for Array. [].valueOf() returns the object [] itself. Since an Array object is not a primitive, the [[DefaultValue]] hint is irrelevant: the return value for an array will be the value of toString().
To quote David Flanagan's JavaScript: The Definitive Guide, which, by the way, is a superb book that should be everyone's first place to get answers to these types of questions:
The details of this object-to-number conversion explain why an empty array converts to the number 0 and why an array with a single element may also convert to a number. Arrays inherit the default valueOf() method that returns an object rather than a primitive value, so array-to-number conversion relies on the toString() method. Empty arrays convert to the empty string. And the empty string converts to the number 0. An array with a single element converts to the same string that that one element does. If an array contains a single number, that number is converted to a string, and then back to a number.
The second type of answer to the "why" question, other than "because the spec says", gives some explanation for why the behavior makes sense from the design perspective. On this issue I can only speculate. First, how would one convert an array to a number? The only sensible possibility I can think of would be to convert an empty array to 0 and any non-empty array to 1. But as Wayne's answer revealed, an empty array will get converted to 0 for many types of comparisons anyway. Beyond this, it's hard to think of a sensible primitive return value for Array.valueOf(). So one could argue that it just makes more sense to have Array.valueOf() be the default and return the Array itself, leading toString() to be the result used by ToPrimitive. It just makes more sense to convert an Array to a string, rather than a number.
Moreover, as hinted by the Flanagan quote, this design decision does enable certain types of beneficial behaviors. For instance:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
This behavior allows you to compare a single-element array to numbers and get the expected result.
console.log('-- types: undefined, boolean, number, string, object --');
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof NaN); // number
console.log(typeof false); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof []); // object
console.log(typeof {}); // object
console.log('-- Different values: NotExist, Falsy, NaN, [], {} --');
console.log('-- 1. NotExist values: undefined, null have same value --');
console.log(undefined == null); // true
console.log('-- 2. Falsy values: false, 0, "" have same value --');
console.log(false == 0); // true
console.log(false == ""); // true
console.log(0 == ""); // true
console.log('-- 3. !NotExist, !Falsy, and !NaN return true --');
console.log(!undefined); // true
console.log(!null); // true
console.log(!false); // true
console.log(!""); // true
console.log(!0); // true
console.log(!NaN); // true
console.log('-- 4. [] is not falsy, but [] == false because [].toString() returns "" --');
console.log(false == []); // true
console.log([].toString()); // ""
console.log(![]); // false
console.log('-- 5. {} is not falsy, and {} != false, because {}.toString() returns "[object Object]" --');
console.log(false == {}); // false
console.log({}.toString()); // [object Object]
console.log(!{}); // false
console.log('-- Comparing --');
console.log('-- 1. string will be converted to number or NaN when comparing with a number, and "" will be converted to 0 --');
console.log(12 < "2"); // false
console.log("12" < "2"); // true
console.log("" < 2); // true
console.log('-- 2. NaN can not be compared with any value, even if NaN itself, always return false --');
console.log(NaN == NaN); // false
console.log(NaN == null); // false
console.log(NaN == undefined); // false
console.log(0 <= NaN); // false
console.log(0 >= NaN); // false
console.log(undefined <= NaN); // false
console.log(undefined >= NaN); // false
console.log(null <= NaN); // false
console.log(null >= NaN); // false
console.log(2 <= "2a"); // false, since "2a" is converted to NaN
console.log(2 >= "2a"); // false, since "2a" is converted to NaN
console.log('-- 3. undefined can only == null and == undefined, and can not do any other comparing even if <= undefined --');
console.log(undefined == null); // true
console.log(undefined == undefined); // true
console.log(undefined == ""); // false
console.log(undefined == false); // false
console.log(undefined <= undefined); // false
console.log(undefined <= null); // false
console.log(undefined >= null); // false
console.log(0 <= undefined); // false
console.log(0 >= undefined); // false
console.log('-- 4. null will be converted to "" when <, >, <=, >= comparing --');
console.log(12 <= null); // false
console.log(12 >= null); // true
console.log("12" <= null); // false
console.log("12" >= null); // true
console.log(0 == null); // false
console.log("" == null); // false
console.log('-- 5. object, including {}, [], will be call toString() when comparing --');
console.log(12 < {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log(12 > {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log("[a" < {}); // true, since {}.toString() is "[object Object]"
console.log("[a" > {}); // false, since {}.toString() is "[object Object]"
console.log(12 < []); // false, since {}.toString() is "", and then converted to 0
console.log(12 > []); // true, since {}.toString() is "", and then converted to 0
console.log("[a" < []); // false, since {}.toString() is ""
console.log("[a" > []); // true, since {}.toString() is ""
console.log('-- 6. According to 4 and 5, we can get below weird result: --');
console.log(null < []); // false
console.log(null > []); // false
console.log(null == []); // false
console.log(null <= []); // true
console.log(null >= []); // true
In if (arr), it is always evaluated (ToBoolean) to true if arr is an object because all objects in JavaScript are truthy. (null is not an object!)
[] == false is evaluated in iterative approach. At first, if one side of == is primitive and the other is object, it converts object to primitive at first, then converts both sides to Number if both sides are not string (string comparison is used if both sides are strings). So the comparison is iterated like, [] == false -> '' == false -> 0 == 0 -> true.
Example:
const array = []
const boolValueOfArray = !!array // true
It happens because
ToNumber(ToPrimitive([])) == ToNumber(false)
[] is empty Array object → ToPrimitive([]) → "" → ToNumber("") → 0
ToNumber(false) → 0
0 == 0 → true
An array with elements (regardless if 0, false or another empty array), always resolves to true using Abstract Equality Comparison ==.
1. [] == false; // true, because an empty array has nothing to be truthy about
2. [2] == false; // false because it has at least 1 item
3. [false] == false; // also false because false is still an item
4. [[]] == false; // false, empty array is still an item
But using a Strict Equality Comparison ===, you are attempting to evaluate the variable's content as well as its data type that is why:
1. [] === false; // false, because an array (regardless of empty or not) is not strictly comparable to boolean `false`
2. [] === true; // false, same as above, cannot strictly compare [] to boolean `true`
3. [[]] === false; // true, because see #1
It seems no one is talking about why
(arr && arr == false) is true. Just for people who are not sure about the operator precedence, accourding to MDN, == has higher precedence than &&, so it is actually (arr && (arr == false)). After wildcard's answer , it's true && true, so it's true.
var arr = [];
if (arr && arr == false) console.log("...what??");
You can empty a JavaScript Array by referencing it to a new array, using list = [] or deleting the elements of the currently referenced array list.length = 0.
Source: JavaScript Empty Array
None of the above helped me, when trying to use the knockout.js mapping plugin, perhaps since an "empty array" isn't really empty.
I ended up using: data-bind="if: arr().length" which did the trick.
This is specific to knockout, not the OP's question, but maybe it will help someone else browsing here in a similar situation.

Explicit boolean conversion

I have a variable which is either set to something or is undefined. I wish to pass to a function true if the variable is defined else false. Here is the function:
function f(areRowsSelectable){...}
Which of the following would you do?
f(v);
f(v?true:false);
Or something else?
I usually use double negation (which means applying the logical NOT operator twice) for explicit boolean conversion:
!!v
Examples:
!!'test' // true
!!'' // false
!!0 // false
!!1 // true
!!null // false
!!undefined // false
!!NaN // false
Alternatively, also Boolean(v) would work.
I would use the "typeOf" guard method.
It does not accept "truthy" arguments, so it depends on your function whether you can use it.
The tests are basically the same as czosel's answer, but his answer returns "truthy" while mine only accepts boolean true as true.
var tests = [
//filled string
'test',
//empty string
'',
//Numeric empty
0,
//Numeric filled
1,
//Null
null,
//Completely undefined
,
//undefined
undefined,
//Not-A-Number numeric value
NaN,
//Boolean true
true
];
for (var t = 0; t < tests.length; t++) {
var test = tests[t];
var results = {
test: test,
isTruthy: !!test,
isBoolTrue: (typeof test != "boolean" ? false : test),
isDefined: (test !== void 0)
};
console.log(results);
}
EDIT 1
Since the question could be interpreted in several ways, i have included a couple of more tests.
isTruthy matches czosel's answer. Registers truthy values like 1 as true.
isBoolTrue was my first interpretation where it checks strictly whether a value is boolean true.
isDefined simply returns if the variable contains anything at all.

'&&' operator in Javascript vs in Java

I am currently reading JavaScript from JavaScript: The Definitive Guide. On page 76, there is this statement written,
o && o.x // => 1: o is truthy, so return value of o.x
Being a Java programmer I want to ask, why is it returning 1 instead of 'true' In Java this was not the case, but anyway I know JavaScript is different but the Logical AND mechanism is the same everywhere.(In C it returns 1 as true.)
I am asking is, why does it makes sense for this behavior at all?
Is there any way, I can ensure to return only the true or false values?
As per the Spec for Binary Logical Operators
The value produced by a && or || operator is not necessarily of type
Boolean. The value produced will always be the value of one of the two
operand expressions.
This is a feature used in javascript a lot, one common use case is to assign a default value to a variable if it is not defined. Like assume you are expecting a options object as a param but is not mandatory so the user may not pass it
function x(options){
options = options || {};
//now your can access optionx.a without fearing whether options is undefined
}
You can do something like !!(o && o.x) to always get a true/false
if we have:
expr1 && expr2
&& Returns 'expr1' if it can be converted to false; otherwise, returns 'expr2'. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
So if we have:
Var xyz = a && b; //where a is undefined(false) and b is 123, then it will allocate undefined.
In case of if statements, these values are specifically converted to boolean.
Refer the following link: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators"
You can use Boolean(o && o.x); to get true or false
It's returning the value of the right operand. If the value of o.x was true, it would return true. If the value of o.x was 'banana', it would return 'banana'.
var o = {x:true};
console.log(o && o.x);
Technically && operator implemented to return the first operand if it's value is not zero, and returns the second operand otherwise in a lot of languages including Java, C/C++, Javascript, Perl...
While most of the languages accepts any type of operands, Java forces you to use boolean operands so it always returns true or false.
In order to force a boolean result in Javascript use:
Boolean(a && b)
This behaviour is called coercion. Coercion is the action of forcing an object to behave like other type, and the logical operators can produce coercion when trying to access the value of the object to be evaluated.
It is important to remember the table for truthy and falsy values, because due to coercion, different results can be obtained.
false produces false
0 produces false
“” produces false
NaN produces false
null produces false
undefined produces false
Everything else produces true, including the text "0" and "false", functions, arrays and empty objects.
Given the rules for logic operators, exists short-circuit evaluation in JavaScript, e.g:
0 && 1; //-> 0, falsy value
!(0 && 1); //-> true, falsy value negated
!!(0 && 1); //-> false, boolean falsy value
void 0 && alert("1") //-> undefined (void produces undefined)
[] && Math.ceil(9.1) //-> 10, truthy value
{} && someFunc() //-> the result of someFunc()
0 || null; //-> null, falsy value
null || "0"; //-> "0", truthy value
"" || void 1; //-> undefined, falsy value
!!(+"5px" || {}); //-> true, boolean truthy value
Coercion is useful when you have to validate default values, in order to prevent errors, e.g.
function divide (a, b) {
a = +a; //-> coerced to number
b = +b; //-> coerced to number
if (!a) return 0; //-> NaN or zero
return b && a / b; //-> b must be a number different from zero
}
divide(); //-> 0
divide(5); //-> NaN, no error thrown!
divide(5, "a"); //-> NaN, no error thrown!
divide(5, 0); //-> 0, division by zero prevented!
divide(49, 6); //-> 8.1666
If you want to prevent returning NaN, just add another coercion in the return statement:
return (b && a / b) || 0;
You can check other coercion cases: JavaScript Coercion
Happy coding!

Why does this code produce 3 in JavaScript?

Why does the following code produce a == 3?
var x = "abc";
var y = 3;
var z = "xyz";
var a = x && y || z;
http://jsfiddle.net/thinkingmedia/qBZAL/
I would have expected this to result in a == true.
Why is the logical operator evaluating "abc" as true but doesn't evaluate 3 as true. Instead it produces 3 as the result.
Furthermore, if you change y = 0 then a == "xyz" which means that && treated 0 as false. What happen to treating a number as a number?
What's going on here with the logical operators?
This is to be expected.
In JavaScript (and many other languages), not only Booleans themselves are true or false, but other objects can be truthy or falsey as well (See the docs on mdn):
The value […] is converted to a boolean value, if necessary. If value is […] is 0, -0, null, false, NaN, undefined, or the empty string (""), [it is] false. All other values, including any object or the string "false", create […] true.
The logical operators || and && don't return true or false, rather they return the last argument to influence whether they are truthy or falsey (reference):
expr1 && expr2 – Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
expr1 || expr2 – 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.
The first step is to evaluate "abc" && 3.
false && 3 would return false,
true && 3 would return 3.
"abc" is not false, so JavaScript takes the second part, i.e. 3.
The second step is to evaluate 3 || "xyz". Here, JavaScript takes the first value which is not null, i.e. 3. This is similar to this.firstObject ?? this.defaultValue in C#: the second part is taken only when the first part is null.
the side effect is that you can do things like this:
x = x || {};
to set a variable to a default if it is not set.
Or
TrackingManager && TrackingManager.track("user was here")
to avoid bulkier if statements.

Categories