Given this script:
var number = NaN;
if (!number) {
alert("yes");
}
alert(number == false);
Why does the first expression `!number evaluates to true, while the second expression number == false evaluates to false?
http://jsfiddle.net/8EWG4/
Keep a look in this article:
http://www.smashingmagazine.com/2011/05/30/10-oddities-and-secrets-about-javascript/
There's some tricks about javascript, including informations about NaN:
NaN is a Number
You thought null being an object was ridiculous? Try dealing with the idea of NaN — “not a number” — being a number! Moreover, NaN is not considered equal to itself! Does your head hurt yet?
alert(typeof NaN); //alerts 'Number'
alert(NaN === NaN); //evaluates false
In fact NaN is not equal to anything. The only way to confirm that something is NaN is via the function isNaN().
The ECMAScript specification says so:
x == y is defined as (11.9.3):
If x is NaN, return false.
And ! calls ToBoolean (9.2) first (and then returns the opposite):
The result is false if the argument is +0, −0, or NaN; otherwise the result is true
To evaluate a variable is NaN ( not a number ), consider using isNaN(number) . It will give you correct answer.
From wikipedia - JavaScript syntax, boolean:
When used in a logical context, 0, -0, null, NaN, undefined, and the empty string ("") evaluate as false due to automatic type coercion.
!NaN == true
So, as NaN is coerced to false, !NaN evaluates to true.
However, NaN is not equal to false - it is a different type/value.
Related
Given the following code:
if ("string") {
console.log('true!');
}
//logs "true" to the console
if ("string"==true) {
console.log('true!');
}
//doesn't log anything
Why does this happen? I thought "string" was being cast to a number, as is the boolean. So true becomes 1, and "string" becomes NaN. The second if statement makes sense, but I don't see why the first statement causes the inner loop to be evaluated. What's going on here?
It is being cast to Boolean. Any non-empty string evaluates to true.
From the ECMAScript Language Specification:
12.5 The if statement
Semantics
The production IfStatement: if ( Expression ) Statement else Statement is evaluated as follows:
Let exprRef be the result of evaluating Expression.
If ToBoolean(GetValue(exprRef)) is true, then
Return the result of evaluating the first Statement.
Else,
Return the result of evaluating the second Statement.
9.2 ToBoolean
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
Table 11 - ToBoolean Conversions
Undefined: false
Null: false
Boolean: The result equals the input argument (no conversion).
Number: The result is false if the argument is +0, -0, or NaN; otherwise the result is true.
String: The result is false if the argument is the empty String (its length is zero);
otherwise the result is true.
Object: true
As far as the == operator is concerned, it's complicated, but the gist of it is that if you compare a number to a non-number the latter is converted into a number. If you compare a boolean against a non-boolean, the boolean is first converted to a number, and then the previous sentence applies.
See section 11.9.3 for details.
// Call this x == y.
if ("string" == true)
// Rule 6: If Type(y) is Boolean,
// return the result of the comparison x == ToNumber(y).
if ("string" == Number(true))
// Rule 5: If Type(x) is String and Type(y) is Number,
// return the result of the comparison ToNumber(x) == y.
if (Number("string") == Number(true))
// The above is equivalent to:
if (NaN == 1)
// And NaN compared to *anything* is false, so the end result is:
if (false)
Non-empty strings are truthy, but are not necessarily equivalent to true.
== is a "soft" equality operator.
It uses type coercion to compare two equivalent objects as equal.
All of the following are true:
42 == "42"
0 == false
0 == ""
[] == ""
{} == "[object Object]"
"1" == true
Aribtrary strings are not equivlant to any primitive values.
However
When you write if (something), the if will execute if something is "truthy".
All values are truthful except the following:
false
0
NaN
""
null
undefined
if ("string"===true)
Should be written this way.
"string" is a string which is not null. In JavaScript everything not being null evaluates "true". So: if("string") is the same as if("string" != null) but "string" is not true, it is still a string value.
I think this is happening because in the first example, your "string" is a non-null object, which translates to true in this context, whereas in the second example, you're asking if this String object is the same as the Boolean object, which it's not, so it translates to false.
if ("string") {
console.log('true!');
}
As you may already know, if evaluates a boolean expression. So it checks
if((Boolean)"string")
Since (bool)string is true it passes. But in the case of
if ("string"==true) {
console.log('true!');
}
You are trying to equate a string with a bool, which obviously compares them and returns false.
Simple:
if("string") is evaluated as a boolean. Any value that isn't false is true, no conversion to number or anything of that sort.
Comparing "string" to a boolean value true will obviously yield false.
From the ECMA 262 reference, if you convert implicitly a String to Boolean, and the String is other than the empty String, it will evaluate to true.
Check here
I was tring a few things in the console.
!5 is actually false
0 is a falsy value, so
0 == !5 is true
Okay, but when i tried this
!0 is true
5 is a truthy, so
5 == !0 should be true
But its not, the console says false. Why is this happening?
The reason the last line is false is that the == isn't a simple boolean conversion. It usually tries to convert operands with non-matching types down to a number.
So the 5 doesn't need conversion since it's already a number but !0, which is true, does. The value true gets converted to 1, so it doesn't equal 5.
You can infer from this that 1 == !0 will be true, and indeed it is.
This is detailed in the ES5 spec in the Abstract Equality Comparison Algorithm, step 7, which says of the comparison x == y:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
So the right-hand boolean is coerced to a number with ToNumber. In this case, ToNumber says:
The result is 1 if the argument is true.
if([] == false) alert('empty array is false');
alert(+[]) // alert 0
if([]) alert('empty array is true');
They both will run the alert
Demo
Both current answers here are correct, but I'd like to add a more detalied explanation based on the language specification. The reason for the apparently contradictory outcomes is that if statements and equality comparisons are evaluated differently.
In the case of an if(expression) statement, the expression is evaluated and then converted to the boolean type (§ 12.5). Arrays are Objects, and when an Object is converted to Boolean, the result is always true (§ 9.2).
Equality comparisons with == follow a different set of rules, detailed on § 11.9.3. The comparison may require multiple type conversions, until both operands are the same type. The order of the operands is also important. According to that algorithm, we can see that the comparison [] == false is actually a four-step operation:
There is a Boolean involved, so it's converted to a Number first (step 7 of the algorithm). So it becomes:
[] == 0
Then the array is converted to its primitive value (see § 9.1 and § 8.12.8), and becomes an empty string (step 9). So:
"" == 0
When comparing a String to a Number, the String is converted to Number first (step 5, following the rules described on § 9.3.1):
0 == 0
Now that we have two Numbers, the comparison evaluates to true according to step 1.c.iii.
It's because of type coercion of the == (equality) operator.
An empty array is considered truthy (just like an empty object), thus the second alert is called.
However, if you use ([] == false), your array is coerced to its string representation* which is "" which then is considered as a falsy value, which makes the condition true thus triggering the first alert too.
If you want to avoid type coercion, you have to use the === (identity) operator which is the preferred and by the famous Douglas Crockford promoted way to compare in javascript.
You can read more on that matter in this exhaustive answer.
*(Object.prototype.toString is called on it)
EDIT:
fun with JS-comparison:
NaN == false // false
NaN == true // also false
NaN == NaN // false
if(NaN) // false
if(!NaN) // true
0 == '0' // true
'' == 0 // true
'' == '0' // false !
This shows you the real "power" of Comparison with == due to the strange rules mentioned in bfavarettos answer.
There is a difference between evaluating a value as a boolean, and comparing it to true or false.
Whe using the == operator, the values are converted so that the types correspond. The [] value converted to the empty string "", and converting that in turn to a boolean gives false, so [] == false becomes true.
Evaluating [] as a boolean value will return true, because it is not a 'falsy' value, i.e. 0, false, null, "", NaN or undefined.
In the below code :
console.log( (false || "test") ? "first" : "second") );
The o/p of first part is test ( false || "test") , so how is my final o/p first ? What happens in general when the conditional operator can't evaluate an expression as True or False ?
|| is OR. So when a boolean is needed, (false || "test") is equivalent to "test". And "test" is coerced as true when a boolean is needed (0 wouldn't, "" wouldn't, but "0" would be seen as true).
As seen in the ECMAScript specification, an if converts the condition to a boolean using toBoolean :
Every value in javascript, regardless of its type, can be coerced to a boolean value.
Values that coerce to false are called "falsey", and values that coerce to true are called "truthy".
Here's a fiddle demonstrating this coercion.
In this case:
(false || "test") ? "first" : "second")
(false || "test") is logically equivalent to ("test") since false || X is equivalent to X (this is called a disjunctive syllogism, if you're interested in logics).
Any non-empty string in javascript (including the string 'false', have fun with that bug) coerces to true, so the tertiary condition evaluates to true and logs 'first'.
"What happens in general when the conditional operator can't evaluate an expression as True or False ?"
Every expression in JavaScript can be evaluated as true or false because every type is coercible to a boolean.
In your code, the "test" operand will be evaluated effectively as Boolean("test"), which is true.
The values that coerce to false, are:
false (obviously)
NaN
"" (an empty string)
0
null
undefined
Everything else is considered true.
The || operator returns the left hand side if the left hand side is true, otherwise it returns the right hand side.
Thus (false || "test") is "test".
"test" is a true value, so you get:
"test" ? "first" : "second"
The ternary operator returns the value before the : if the value before the ? is a true value (which is is).
What happens in general when the conditional operator can't evaluate an expression as True or False ?
The result of any expression can be evaluated as being a true or false value, so that will never happen.
Because Javascript implicitly casts test to true. While converting strings to boolean, Javascript converts non-empty strings to true, and empty strings to false.
So, since the first operand of the || operator is false, false || "test" expression will return the second argument, which by then will be converted to true. So you will get first as your output.
What is the difference if("test") and if(!!"test"), only judged the false or true;
The question has a double negation expressson, that converts the type to boolean.
e.g.
var x = "test";
x === true; // evaluates to false
var x = !!"test";
x === true; //evalutes to true
!! will convert a "truthy" value in true, and a "falsy" value on false.
"Falsy" values are the following:
false
0 (zero)
"" (empty string)
null
undefined
NaN
If a variable x has any of these, then !!x will return false. Otherwise, !!x will return true.
On the practical side, there's no difference between doing if(x) and doing if(!!x), at least not in javascript: both will enter/exit the if in the same cases.
EDIT: See http://www.sitepoint.com/blogs/2009/07/01/javascript-truthy-falsy/ for more info
!! does type conversion to a boolean, where you are just dropping it in to an if, it is AFAIK, pointless.
There is no functional difference. As others point out,
!!"test"
converts to string to a boolean.
Think of it like this:
!(!("test"))
First, "test" is evaluated as a string. Then !"test" is evaluated. As ! is the negation operator, it converts your string to a boolean. In many scripting languages, non-empty strings are evaluated as true, so ! changes it to a false. Then !(!"test") is evaluated, changing false to true.
But !! is generally not necessary in the if condition as like I mention it already does the conversion for you before checking the boolean value. That is, both of these lines:
if ("test")
if (!!"test")
are functionally equivalent.