Empty arrays seem to equal true and false at the same time
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.
Why do empty JavaScript arrays evaluate to true in conditional structures?
From http://www.sitepoint.com/javascript-truthy-falsy/
The following values are always falsy:
- false
- 0 (zero)
- 0n (BigInt zero)
- "" (empty string)
- null
- undefined
- NaN (a special Number value meaning Not-a-Number!)
All other values are truthy, including "0"
(zero in quotes), "false"
(false in quotes), empty functions, empty arrays ([]
), and empty objects ({}
).
Regarding why this is so, I suspect it's because JavaScript arrays are just a particular type of object. Treating arrays specially would require extra overhead to test Array.isArray()
. Also, it would probably be confusing if true arrays behaved differently from other array-like objects in this context, while making all array-like objects behave the same would be even more expensive.
Empty array is false, but in IF statement it returns true
this is because ==
in JS forces conversion and if one type can be converted to another the return value is true
and here because []
cant be changed or compared with bool it is false
where as if([])
checks for null
and undefined
values and because [] is neither null or undefined it is returning true
check this
Which equals operator (== vs ===) should be used in JavaScript comparisons?
Returning of empty array in Javascript
Because ==
will cause toString()
on the newly created object to be called and it will return ""
and through coercion it will equal false
.
always use ===
.
Conflicting boolean values of an empty JavaScript array
The first one:
[] == false
The ==
operator does type conversion to its operands, in this case the both sides are converted to Number, the steps taken on the Abstract Equality Comparison Algorithm would be:
- object == boolean
- object == number
- string == number
- number == number
In code:
[] == false; // convert false to Number
[] == 0; // convert [] to Primitive (toString/valueOf)
"" == 0; // convert "" to Number
0 == 0; // end
The second comparison, []
is converted to primitive, their valueOf
and toString
methods are executed, but since valueOf
on Array objects, returns the object itself (is inherited from Object.prototype
), then the toString
method is used.
At the end as you see, both operands are converted to Number, and both yield zero, for example:
Number([]) == 0;
Number(false) == 0;
And empty array produces zero when converted to Number because its string representation is an empty string:
[].toString(); // ""
And an empty string converted to Number, yields zero:
+""; // 0
Now, the double negation (!![]
) produces true because all object instances are truthy:
![]; // false, [] is truthy
!![]; // true, negation
The only values that are falsey are:
null
undefined
0
NaN
""
(an empty string)false
Anything else will produce true
when converted to Boolean.
See also:
- JavaScript Coercion Tool
Empty array is falsy, yet [] ? 0 : 1 evaluates to 0
An array is not falsy; this can be demonstrated using console.log(!![])
When doing a left vs. right comparison via the ==
operand JavaScript attempts to coerce the inputs to a common type.
With your first example of [] == false
, the following occurs:
- The right-hand side is found to be
Boolean
so it is converted to aNumber
value, resulting in the comparison being[] == 0
. - Since the left-hand side is an
Object
it is converted to a primitive; in this case aString
via[].toString()
, resulting in the comparison being"" == 0
. - Since the left-hand side is a
String
, it gets converted to anumber
value resulting in0 == 0
. - Since both sides are
Number
primitives, their values are compared, resulting in a truthy condition
With the second example of [] ? 0 : 1
, there is no right-hand value to compare to, so it simply tests if the input is truthy. The array is not undefined
, null
, 0
, ""
or NaN
, so it is treated as truthy and thus the 'true' option is returned: 0
;
To force a non-coercive comparison between two inputs you should use the ===
operand.
Ecma Standard 6th edition Entry on Coercion
JS Coercion Explained
Related Topics
How to Wait for Set of Asynchronous Callback Functions
Convert Base64 String to Arraybuffer
JavaScript Filter Array of Objects
Why Don't We Just Use Element Ids as Identifiers in JavaScript
Jqgrid Incorrect Select Drop Down Option Values in Edit Box
Why Is Mutating the [[Prototype]] of an Object Bad for Performance
What Is the Correct Terminology for JavaScript Promises
Browser JavaScript Stack Size Limit
Getting All Variables in Scope
How to Synchronize a Sequence of Promises
Event Handlers Inside a JavaScript Loop - Need a Closure
Preserving a Reference to "This" in JavaScript Prototype Functions
Over_Query_Limit in Google Maps API V3: How to Pause/Delay in JavaScript to Slow It Down
Difference Between Dates in JavaScript