Difference between Boolan(!x) and Boolean(x==0)? - javascript

Code-snippet 1:
if ( !x ) { /* do stuff */ }
Code-snippet 2:
if ( x == 0 ) { /* do stuff */ }
For what values of x do these two code-snippets differ?
I am asking because, although I read the chapter on == in the spec, I still find it hard to deal with situations like the above (where it is combined with ToBoolean coercion).
btw, I want to know this just for the sake of knowing it (I want to understand the language), so don't bother telling me about === or asking me what x is.
Update: I corrected the fist snippet. I meant !x.

[] == 0 is true; ![] is false
null == 0 is false; !null is true
NaN == 0 is false; !NaN is true
undefined == 0 is false; !undefined is true
!x will check whether x is "falsy".
x == 0 will check whether x is "equivalent to" 0.
Both of these terms are defined by the Javascript spec.

The following will give you true for the first and false for the second snippet:
NaN
null
undefined
And these will give you false for the first and true for the second snippet:
[]
"0" and any other string that converts to 0 using Number(x) such as "00", "000", "+0", and "-0" (which I will now call "noughty strings")
an array containing a single element that is 0, null, undefined or an empty or noughty string.
For everything else you'll get the same result for both snippets, although there may be one or two more cases I haven't thought of.

Here's an interesting one with regard to a non-empty String that has only space characters:
!!" "; // true
" " == true; // false
This is because when you do a == comparison, and one of the values being compared is a number or a boolean, an attempt is made to convert the other value to a number.
The reason you get the different result is that a string with only space characters converts to the number 0 (or falsey), while a string with only spaces converted to boolean via !! is seen as a non-empty string, and therefore true.
So:
var x = " ";
alert( !x ); // false
alert( x == 0 ); // true
EDIT:
Probably the key thing to remember is that when comparing a number or boolean to a non number type, == uses toNumber conversion if possible, while ! uses toBoolean conversion. They're not always the same.
It is easy to see the result of the toBoolean conversion using !!. As in:
alert( !![] ); // true
But you can't really see the result of the toNumber conversion when using ==.
You can, however, use the unary + to see the result of a toNumber conversion. As in:
alert( +[] ); // 0
I'm pretty sure that what happens in the case of an Array, is that it first gets a toString call. Therefore:
// ---------------------toString result-------toNumber result (from string)
alert( +[] ); // "" 0
alert( +[""] ); // "" 0
alert( +[" "] ); // " " 0
alert( +[0] ); // "0" 0
alert( +["0"] ); // "0" 0
alert( +["3"] ); // "3" 3
alert( +[3,4] ); // "3,4" NaN

Short answer: the two are almost always the same but not 100% the same.
An example would be (!'0') which is false whereas ('0' == 0) is true
Details:
From: http://www.joeyjavas.com/2007/08/04/javascript-true-false-checking-for-boolean-values/
Checking if a value is true or false is simple in JavaScript. All values evaluate to true, except for:
0
-0
null
undefined
NaN
empty string
false
Therefore, (!x) will be true for all of the above values of x and only those.
As for (x == 0), it will be true for any value of x which - when converted according to "==" conversion rules - is converted to 0 when compared to a number (for example, Boolean false value). Other examples that compare true to ==0 are objects which generate 0 from their valueOf() methods, or a string '0', or an empty Array ([])

The first test will succeed when x is non-zero, or evaluates to an object (as opposed to null or undefined), or is a non-empty string. So if x is 0 then the condition fails, but if it is "0" then it succeeds.
The second test will succeed when x is convertible to 0. This means it must not be null, undefined, or an object to pass this test. And it may be "0" or "".
In other words, these conditionals are not opposites. The value "0" will pass both tests, for example.

Code Snippet 1 will execute if x is "falsy" value. In Javascript, this means 0, -0, null, undefined, NaN, "", or false. Code Snippet 2, however, will only execute if x is zero. Unlike the first condition, this does not include other "falsy" values.

The difference between the two is that
if ( x ) { ... }
Tests whether x is "truthy"
Whereas
if ( x == 0 ) { ... }
Does type coercion between x and 0.
I presume you mean something like
if (x == 0) vs if (!x)
The main difference is type coercion of x to a number vs checking if x is falsy.
Clearly NaN itself will never equal 0 since its not a number. undefined will also coerce to NaN so that is not caught by == 0 I can't give a good explanation why null is not caught by 0 since Number(null) == 0

After some lookups, have to change my awnser.
There's no simple logic, implicit equality operations follows an algorithm.
http://interglacial.com/javascript_spec/a-11.html#a-11.9.3
I can't sum it up better then what the algoritm describes, it would just get more confusing.
So it's (!x) is equivalent to (typeof x === false) aka (not true)
And (x == 0) gets compared by algorithm.

Related

Why the Sum of Null and zero is zero [duplicate]

I am trying to understand the core of JavaScript. I know it doesnt have much implementation value. If you dont want to answer, just leave it. However, I will appreciate if you could help to understand the following type coercion while applying addition(+).
1.
null + null // 0
2.
null + undefined; // NaN
3.
null + NaN; // NaN
4.
1 + null; //1
5.
true + null; //1
6.
true + [null]; //"true"
I know null is an empty or missing object. I will appreciate, if you can explain steps in type coercion or unary(+) operation here. Thanks for reading the question.
This is covered in 11.6.1 The Addition operator ( + ) - feel free to read it and follow the rules.
The first five cases can be explained by looking at ToNumber:
Value ToNumber(Value)
--------- ---------------
null 0
undefined NaN
NaN NaN
1 1
true 1
And 0 + 0 == 0 (and 1 + 0 == 1), while x + NaN or NaN + x evaluates to NaN. Since every value above is also a primitive, ToPrimitive(x) evaluates to x (where x is not a string) and the "string concatenation clause" was not invoked.
The final case is different in that it results from the ToPrimitive (which ends up calling Array.prototype.toString) on the array which results in a string value. Thus it ends up applying ToString, not ToNumber, and follows as such:
true + [null]
=> true + "" // after ToPrimitive([null]) => ""
=> "true" + "" // after ToString(true) => "true"
=> "true" // via String Concatenation
Conclusions derived from analysing results
true coerces to 1 (and false to 0).
null coerces to 0.
undefined coerces to NaN.
Arrays behave as:
under unary + (+[]):
their first element if length is 1
0 if they're empty
NaN if there's more than 1 element
under binary + (1+[]):
coerces both operators to strings and joins them
All operations on NaN return NaN

JavaScript: When the `condition` portion of a `ternary` or `if` statement does not include `===` or `>=`

In the condition portion of the following ternary statement, does playlist.length equal playlist.length >= 1 ?
var playlist = ["video1", "video2", "video3", "video4", "video5"];
// some code here
alert ((playlist.length) ?
playlist.length + "video(s) remain in the playlist: " + playlist.join (", ") + "."
: "No videos remain in the playlist");
Likewise, in the following snippet of code, does ! playlist.length equal playlist.length === 0 ?
alert ((! playlist.length) ?
"No videos in the playlist."
: playlist.length + " video(s) remain in the playlist: " + playlist.join(", ") + ".");
This is the first time I've seen an example where the condition portion of a ternary or if statement does not include such a notation as === or >=. So I'm not sure how to interpret this.
0 is implicitly converted to false in boolean comparisons in JavaScript. So when the length is 0, that is false. Conversely, any other number is implicitly converted to true in boolean comparisons in JavaScript. So when the length is anything but 0 it is true.
An easy test is to use !! to see the "truthy" value
!!1 === true
!!0 === false
!!6 === true
The part to the left of the ? is simply evaluated for "truthiness". The value 0 is "falsy" so evaluates as false for the purposes of the test. Numeric values other than 0 are "truish" and therefore for this purpose evaluate to true.
All other behaviors of the ternary are the same.
The === and !== simply add the additional constraint that the L-value and R-value must also be the same type.
The two are very similar: !playlist.length and playlist.length === 0.
However, they are not exacty the same. In fact, here:
var playlist1 = [];
var playlist2 = {};
!playlist1.length // true
!playlist2.length // true
playlist1.length === 0 // true
playlist1.length === 0 // false
In that sense !playlist.length also can be used on all kinds of objects, not just arrays.
In any case, when using this on an array, it is a way to check if the array is empty, and works as you have suggested, the same as playlist.length === 0.
In javascript 0 equals false, and any other number value equals true, but if you use === it compare value types too.

Is whitespace equals to integer 0 in Javascript?

My app behaves abnormally and figured the code below is going to else statement unexpectedly.
code
if(" " != 0) {
console.log("whitespace is not zero");
}
else {
console.log("bar");
}
Firebug output
bar
I thought whitespace is a String and comparison against integer zero should return false like the case above but I don't know why it is going to else statement.
Could anyone explain why?
In JS, " " == 0 equals true with loose/lenient comparison, you should use strict equality operator ===/!== instead:
" " !== 0
To get to first condition.
Tests:
console.log(" " == 0); // true
console.log(" " === 0); // false
Loose Comparison Chart:
"" == "0" // false
0 == "" // true
0 == "0" // true
false == "false" // false
false == "0" // true
false == undefined // false
false == null // false
null == undefined // true
" \t\r\n" == 0 // true
Strict Comparison Chart:
"" === "0" // false
0 === "" // false
0 === "0" // false
false === "false" // false
false === "0" // false
false === undefined // false
false === null // false
null === undefined // false
" \t\r\n" === 0 // false
(Examples by Douglas Crockford)
Good Practice:
Whenever possible, use strict equality operator because with loose equality operator, JS does type coercion which is a performance hit and doesn't always yield expected results as shown in above comparison charts.
The other answers have told you how to solve the issue. My answer will attempt to actually explain why you have the issue in the first place (since that was your actual question!)
The behaviour of the == operator is defined in the spec as the "abstract equality algorithm". It states (among other things) the following:
If Type(x) is String and Type(y) is Number, return the result of the
comparison ToNumber(x) == y.
One of the rules of the ToNumber operation on a string is as follows:
The MV of StringNumericLiteral ::: StrWhiteSpace is 0...
Once the exact MV for a String numeric literal has been determined, it is then rounded to a value of the Number type. If the MV is 0, then the rounded value is +0 unless the first non white space character in the String numeric literal is ‘-’, in which case the rounded value is −0.
So we are left with +0 == 0 which fits another rule of the abstract equality algorithm:
If x is the same Number value as y, return true.
This is the case because 0 is the same as +0. Even if one of the numbers was -0 it would return true:
If x is +0 and y is −0, return true.
If x is −0 and y is +0, return
true.
When you use != rather than !==, JavaScript tries to coerce the values on either side to the same type. In this case, I think it converts both to numbers.
" " happens to be 0 as a number. (Try " " * 1. It evaluates to 0.)
This also works with other operators like > or *. So " " > -1 is true and " " * 100 is 0. This also means you can do neat stuff like "6" * "7" and get 42. Unfortunately, this breaks down with + since it is inexplicably overloaded to do both math and string concatenation.
I personally like all of this behavior except for +. Others' opinions vary.
to compare with the number 0, you must use the strict comparison ===
if(" " !== 0) {
console.log("whitespace is not zero");
}
else {
console.log("bar");
}
a "truth table" found here: Which equals operator (== vs ===) should be used in JavaScript comparisons?
because a string with whitespaces is converted to 0. So
To compare:
if(" " !== 0) {
....

In javascript, is an empty string always false as a boolean?

in javascript,
var a = '';
var b = (a) ? true : false;
var b will be set to false.
is this a defined behavior that can be relied upon?
Yes. Javascript is a dialect of ECMAScript, and ECMAScript language specification clearly defines this behavior:
ToBoolean
The result is false if the argument is the empty String (its length is zero);
otherwise the result is true
Quote taken from http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Yes. All false, 0, empty strings '' and "", NaN, undefined, and null are always evaluated as false; everything else is true.
And in your example, b is false after evaluation. (I think you mistakenly wrote true)
var a = '';
var b = (a) ? false : true; // fixed!
console.log(b); // => true
var b will be set to true.
is this a defined behavior that can be relied upon?
As answered above, yes, that is the defined behavior of an empty string in a conditional (an if expression, ||, &&, ? :, ...). (The standard says that the internal ToBoolean operation must be applied.)
The evaluation is different when the empty string is used in a comparison (see Truth, Equality and JavaScript), even though the results are mostly the same:
// conditional (note: evaluation to false prints false here!)
console.log('' ? true : false); // zero length => false
// comparisons
console.log('' == true); // +0 === 1 => false
console.log('' == false); // +0 === +0 => true
console.log('' === true); // different types => false
console.log('' === false); // different types => false
Explanation: Essentially, when the operands of == have different types, JavaScript tries hard to convert them to Numbers, according to their value, (using operations the standard calls ToNumber and ToPrimitive), and then it internally applies ===. But when you use === directly, the types are not converted, so comparing a String to a Boolean is always false.
Roughly speaking, JavaScript conditionals (ToBoolean) test for a defined, non-null, non-zero, non-empty, non-false value (an empty String is ... empty, the Numbers -0 or +0 are ... zero, NaN is not a defined number, but an empty Object is apparently not really empty), or as I like to think, conditionals test for a (true) thing, while == compares the apparent, carefully converted values (ToPrimitive, ToNumber) of its operands, and === looks for exact sameness.
if (X) {} // is X a (true) thing?
if (X == Y) {} // are the values of X and Y same-ish?
if (X === Y) {} // are X and Y exactly the same?
There are more examples in Truth, Equality and JavaScript where this distinction really matters, e.g. '0' is true in a conditional (non-zero length, or, it is a thing), but false in a == comparison (the value is zero). '1' again, is true in both cases (it is a thing and has a non-zero value).
console.log('' ? true : false); // zero length => false
console.log('' == true); // +0 === 1 => false
console.log('0' ? true : false); // non-zero length => true
console.log('0' == true); // +0 === 1 => false
console.log('1' ? true : false); // non-zero length => true
console.log('1' == true); // 1 === 1 => true
var b will be set to true. This is because an empty string counts as a 'falsey' value in JavaScript as do some other values.
Please look at http://www.sitepoint.com/javascript-truthy-falsy/ for falsy values
Examples of expressions that can be converted to false are those that
evaluate to null, 0, the empty string (""), or undefined.
(see MDN Reference)
Yes, you can rely on that behavior.
A shorter way to write it will be:
var b = !!a;

JavaScript type casting

Consider empty JavaScript array:
var a = [];
alert(a == false); // shows true
alert(!a); // shows false!
How to explain this?
What are the rules?
From http://forums.whirlpool.net.au/archive/966449:
a == false:
In this case, the type of the left-hand side is object, the type of the right-hand side is boolean. Javascript first converts the boolean to a number, yielding 0. Then it converts the object to a "primitive", yielding the empty string. Next it compares the empty string to 0. The empty string is converted to a number, yielding 0, which is numerically equal to the 0 on the right-hand side, so the result of the entire expression is true.
See §11.9.3 of the ECMAScript spec for all the gory details.
(!a):
In this case Javascript converts the object to the boolean true, then inverts it, resulting in false.
The ! operator checks whether its operand is "falsy".
The following are true:
!false
!0
!null
!NaN
!undefined
!""
The == operator checks for loose equality, which has nothing to do with falsiness.
Specifically, a == b will convert to operands to numbers, then compare the numbers.
Strings containing numbers convert to the numbers that they contain; booleans convert to 0 and 1.
Objects are converted by calling valueOf, if defined.
Thus, all of the following are true:
"1" == 1
"0" == false
"1" == true
"2" != true
"2" != false
({ valueOf:function() { return 2; } }) == 2
({ valueOf:function() { return 1; } }) == true
The == operator when one of the operands if Boolean, type-converts the other to Number.
[] == 0;
Is equivalent to:
0 == 0;
You can see the complete details of The Abstract Equality Comparison Algorithm on the specification.
As you can see, an empty array object, when converted to Number, produces 0:
+[]; // 0
Number(0);
This is really because its toString method produces an empty string, for example:
[].toString(); // ""
+""; // 0
Number(""); // 0
When comparing an object to a primitive value via the == operator, the object coerces into an primitive value itself (number or string). In this case [] coerces into 0, then false coerces into 0:
[] == false
0 == false
0 == 0
which is true.
The ! operator coerces into boolean and then inverts the value. [] into boolean is true (like with any object). Then invert to become false
![]
!true
false
Not sure if this answers the question, but there is a new library for getting around all of Javascript's Typecasting weirdnesses:
Typecast.js
In a sentence, Typecast solves all the simple problems, so you can focus on the big ones. Typecast fixes what's wrong with Javascript by creating a complete platform for strongly-typed variables in Javascript.

Categories