Unary + operator in JavaScript applied to ' ' (string with space) [duplicate] - javascript

Today when I was doing some experiments with ==, I accidentally found out that "\n\t\r" == 0. How on earth does "\n\t\r" equal to 0, or false?
What I did is:
var txt = "\n"; //new line
txt == 0; //it gives me true
And that really annoy me. So I did more:
var txt = "\r"; //"return"
txt == 0; //true
var txt = "\t"; //"tab"
txt == 0; //true
It does not make sense, at all. How's that happen? And more crazy is this:
//Checking for variable declared or not
var txt ="\n\t\r";
if(txt!=false){
console.log("Variable is declared.");
}else{
console.log("Variable is not declared.");
}
What it gives me is Variable is not declared.
How is it equal to 0, or false???

This behaviour might be surprising but can be explained by having a look at the specification.
We have to look at the what happens when a comparison with the equals operator is performed. The exact algorithm is defined in section 11.9.3.
I built a simple tool to demonstrate which algorithm steps are executed: https://felix-kling.de/js-loose-comparison/
string == integer
The step we have to look at is #5:
5. If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
That means the string "\n" ("\r", "\t") is converted to a number first and then compared against 0.
How is a string converted to a number? This is explained in section 9.3.1. In short, we have:
The MV (mathematical value) of StringNumericLiteral ::: StrWhiteSpace is 0.
where StrWhiteSpace is defined as
StrWhiteSpace :::
StrWhiteSpaceChar StrWhiteSpace_opt
StrWhiteSpaceChar :::
WhiteSpace
LineTerminator
This just means that the numerical value of strings containing white space characters and/or a line terminator is 0.
Which characters are considered as white space characters is defined in section 7.3.
string == boolean
The step we have to look at is #7:
7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
How booleans are converted to numbers is pretty simple: true becomes 1 and false becomes 0.
Afterwards we are comparing a string against a number, which is explained above.
As others have mentioned, strict comparison (===) can be used to avoid this "problem". Actually you should only be using the normal comparison if you know what you are doing and want this behaviour.

Because JavaScript is a loosely typed language, it attempts to type cast your 1st side of the comparison to the other so that they would match each other.
Any string which does not contain a number, becomes 0 when compared to an integer, and becomes true (Except in certain situations), when compared to a Boolean.
Light reading material.

txt is not a Boolean, so it will never be false. It can be undefined though.
var txt ="\n\t\r";
if(txt !== undefined) { //or just: if (txt)
console.log("Variable is declared.");
} else {
console.log("Variable is not declared.");
}
//=> will log: 'Variable is declared.'
By the way, a declared variable may be undefined (e.g. var txt;).
If you do a stricter comparison (without type coercion, using ===), you'll see that
var txt = '\n'; txt === 0; //=> false
var txt = '\r'; txt === 0; //=> false
var txt = '\t'; txt === 0; //=> false
See also

The reason is that "\n\t\r" just as " " are treated as empty strings.
If you use == it will return true but if you use === it will return false.
If you want to test for existence you should use something like
if(typeof strName !== 'undefined') {
/*do something with strName*/
} else {
/*do something without it*/
}

Whenever you use the == operator and try to compare a string to a number, the string will first be converted to a number. Thus: alert("\n\r"==0) becomes: alert(Number("\n\r")==0)
The Number constructure is kind of interesting. It will first strip whitespace then decide if the number is a not a number or not. If NaN, then the result is "NaN". If the string is empty, then the result is 0.
alert(Number()) alerts 0
alert(Number("")) alerts 0
alert(Number(" \n \r \n \t")) alerts 0
alert(Number("blah")) alerts NaN
alert(Number("0xFF")) alerts 255
alert(Number("1E6")) alerts 1000000
To check if the result is NaN use isNaN()
Thus: alert(isNaN("blah")) alerts true
Thus: alert(isNaN("")) alerts false
Thus: alert(isNaN("\n")) alerts false
Thus: alert(isNaN(" ")) alerts false
however do note that NaN will never equal NaN:
var nan=Number("geh");alert(nan==nan); alerts false
Update:
if you want to check if both sides are NaN, then you'd convert both to boolean values first like so:
var nan=Number("geh");alert(!!nan==!!nan); alerts true
or better yet
var nan=Number("geh");
alert(isNaN(nan)&& isNaN(nan));

Related

why do parseInt and isNaN in JavaScript have inconsistent behavior?

I'm using node.js with v8.11.3.
parseInt("") returns NaN, but isNaN("") returns false:
console.log(
parseInt(''),
isNaN('')
);
another example:
console.log(
parseFloat('0x5'),
parseInt('0x5')
);
Per MDN docs, parseInt:
If the first character cannot be converted to a number, parseInt returns NaN.
There is no first character in the empty string - it cannot be converted to a number, so NaN is returned.
But isNaN is different. As the first paragraph of MDN says:
Note: coercion inside the isNaN function has interesting rules; you may alternatively want to use Number.isNaN(), as defined in ECMAScript 2015.
...
When the argument to the isNaN function is not of type Number, the value is first coerced to a Number.
The empty string, when coerced to a Number, is 0:
const result = Number('');
console.log(result + ' : ' + typeof result);
You might try using parseInt and then checking to see if the result is NaN or not:
const possibleInt = parseInt('');
console.log(Number.isNaN(possibleInt));
The use of Number() just shuffles the problem around. For example:
parseInt("14px"); // 14
parseInt("abc"); // NaN
parseInt(""); // NaN (i.e. null string is a number)
versus use of isNaN:
isNaN("14px"); // false
isNaN("abc"); // true
isNaN(""); // false
versus use of Number():
Number("14px"); // NaN
Number("abc"); // NaN
Number(""); // 0
And, making it more complicated, you can't even do:
parseInt(x) == NaN ? 0 : parseInt(x);
because comparisons with NaN are always false, even NaN == NaN is false.
The simplest that I found was:
x=="" || !isNaN(x) ? 0 : parseInt(x);
but this assumes that the null string is the only anomaly, so it may not work in all cases.

Is a string of whitespace truthy or falsy in JavaScript?

This expression ' ' == true returns false, which means ' ' is falsy,
However
if(' ') { console.log(' true ') } else { console.log(' false ') } ,
gets the result true.
Now I am confused, whether the string of whitespace is truthy or falsy?
The string ' ' is a "truthy" value.
Here is a list of the "falsy" values:
false
null
undefined
0
NaN
''
You have to understand that "truthy" is not the same thing as true. A value can be "truthy" without being true. For example, if we did 5 == true, we would get false, even though 5 is a "truthy" value.
In general, pretty much every value is "truthy" (excluding the ones mentioned above). But, the easiest way to check if something is "truthy"/"falsy" is by doing something like this:
var value = valueToTest;
if (value) {
console.log('Truthy!');
} else {
console.log('Falsy!');
}
Is a string of whitespace truthy or falsy?
It's truthy, as others indicated. However, your comparsion
' ' == true
is not checking whether ' ' is truthy. It's comparing two values, which is a different thing and uses specific comparison rules. The JS spec is that any == comparison with a boolean first coerces the boolean to a number:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
So your code is equivalent to
' ' == Number(true)
which is the same as
' ' == 1
Next, to compare a string and a number, JS converts the string to a number. Again, quoting the spec:
If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
So we now have
Number(' ') == 1
Number(' ') is 0. The spec says:
The MV of StringNumericLiteral ::: StrWhiteSpace is 0.
So this becomes
0 == 1
which, as you found, is false. See http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.3 for details.
As other answers have explained not being equal (==) to true is not the same as being falsy. Falsy is a different concept, which roughly means the value to which an expression is coerced when a boolean is required (such as the condition of an if statement) is false.
in first case expression you are comparing ' ' whitespace string with bool value true and that will surely result in false as ' ' is not equal to true.
in second case expression you are simply writing ' ' whitespace in conditional check in if statement. according to the execution rule of if statement if value is present that it will evaluate to true. and whitespace character is not null so it will execute code block for true statement.
Hope this will help.
following value will evaluated to false if directly placed inside if statement test.
false
null
nil
undefined
NaN
''
0
values other than above will evaluate to true
From your code ' ' == true you are comparing string with a boolean so its obvious those 2 things are totally different and hence you get return as false
In second case i.e. if(' ') you are checking whether you have an object or a null. Here ' ' is a valid non-null object hence you get result as true.
' ' is equal to 32 in ASCII. so , ' ' == true means 32 == true, if(' ')" means if (32).

Ternary operator strange behavior while doing comparison of number

Basically below code is doing comparision of rowind variable and displays alert, but somehow it gives output as Not Zero even if it is zero then also it gives output as "Not Zero", can any one let me know what can be it reason?
<head>
<script language="javascript" type="text/javascript">
var rowind = 0;
var newind = ((rowind == '')) ? "Blank" : "Some number";
//Output is Blank
alert(newind);
</script>
</head>
<body>
</body>
</html>
You are checking whether the variable rowind is equal to empty string in your condition.
((rowind == '')) // this will return as false since you variable is not an empty string. Rather it contains a string with 0 character
if you want to compare the string, use the following.
((rowind == '0')) //This will return true since the string is as same as the variable.
Update
The question you are asking is related to javascript type casting.
The MDN Doc
Equality (==)
The equality operator converts the operands if they are not of the same > type, then applies strict comparison. If both operands are objects, then > JavaScript compares internal references which are equal when operands > refer to the same object in memory.
The above explains how the == operator works in javaascript.
In your example, the '' is converted to a number since it is being compared with a type number variable. so javascript treats '' as a number and '' is equal to 0. thus returns true in your condition.
console.log(0 == '0'); //True
console.log(0 == ''); //True
console.log('' == '0'); //False
The following is the strict comparison used as an example.
console.log(3 == '3') //True
console.log(3 === '3') //False
0 == '' returns true in javascript
The left operand is of the type Number.
The right operand is of the type String.
In this case, the right operand is coerced to the type Number:
0 == Number('')
which results in
0 == 0 // which definitely is true
And yes
0 === '' will return false
As , the identity operator === does not do type coercion, and thus does not convert the values when comparing.
The comparison is between strings and '0' does not equal ''.
Because '0' != '' doesn't cast any of them to Boolean, because they are of the same type - String.

Javascript string/integer comparisons

I store some parameters client-side in HTML and then need to compare them as integers. Unfortunately I have come across a serious bug that I cannot explain. The bug seems to be that my JS reads parameters as strings rather than integers, causing my integer comparisons to fail.
I have generated a small example of the error, which I also can't explain. The following returns 'true' when run:
console.log("2" > "10")
Parse the string into an integer using parseInt:
javascript:alert(parseInt("2", 10)>parseInt("10", 10))
Checking that strings are integers is separate to comparing if one is greater or lesser than another. You should always compare number with number and string with string as the algorithm for dealing with mixed types not easy to remember.
'00100' < '1' // true
as they are both strings so only the first zero of '00100' is compared to '1' and because it's charCode is lower, it evaluates as lower.
However:
'00100' < 1 // false
as the RHS is a number, the LHS is converted to number before the comparision.
A simple integer check is:
function isInt(n) {
return /^[+-]?\d+$/.test(n);
}
It doesn't matter if n is a number or integer, it will be converted to a string before the test.
If you really care about performance, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
return function(n) {
return re.test(n);
}
}());
Noting that numbers like 1.0 will return false. If you want to count such numbers as integers too, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
var re2 = /\.0+$/;
return function(n) {
return re.test((''+ n).replace(re2,''));
}
}());
Once that test is passed, converting to number for comparison can use a number of methods. I don't like parseInt() because it will truncate floats to make them look like ints, so all the following will be "equal":
parseInt(2.9) == parseInt('002',10) == parseInt('2wewe')
and so on.
Once numbers are tested as integers, you can use the unary + operator to convert them to numbers in the comparision:
if (isInt(a) && isInt(b)) {
if (+a < +b) {
// a and b are integers and a is less than b
}
}
Other methods are:
Number(a); // liked by some because it's clear what is happening
a * 1 // Not really obvious but it works, I don't like it
Comparing Numbers to String Equivalents Without Using parseInt
console.log(Number('2') > Number('10'));
console.log( ('2'/1) > ('10'/1) );
var item = { id: 998 }, id = '998';
var isEqual = (item.id.toString() === id.toString());
isEqual;
use parseInt and compare like below:
javascript:alert(parseInt("2")>parseInt("10"))
Always remember when we compare two strings.
the comparison happens on chacracter basis.
so '2' > '12' is true because the comparison will happen as
'2' > '1' and in alphabetical way '2' is always greater than '1' as unicode.
SO it will comeout true.
I hope this helps.
You can use Number() function also since it converts the object argument to a number that represents the object's value.
Eg: javascript:alert( Number("2") > Number("10"))
+ operator will coerce the string to a number.
console.log( +"2" > +"10" )
The answer is simple. Just divide string by 1.
Examples:
"2" > "10" - true
but
"2"/1 > "10"/1 - false
Also you can check if string value really is number:
!isNaN("1"/1) - true (number)
!isNaN("1a"/1) - false (string)
!isNaN("01"/1) - true (number)
!isNaN(" 1"/1) - true (number)
!isNaN(" 1abc"/1) - false (string)
But
!isNaN(""/1) - true (but string)
Solution
number !== "" && !isNaN(number/1)
The alert() wants to display a string, so it will interpret "2">"10" as a string.
Use the following:
var greater = parseInt("2") > parseInt("10");
alert("Is greater than? " + greater);
var less = parseInt("2") < parseInt("10");
alert("Is less than? " + less);

Why is `'\t\n ' == false` in JavaScript?

In JavaScript...
'\t\n ' == false // true
I can assume that any string that consists solely of whitespace characters is considered equal to false in JavaScript.
According to this article, I figured that false would be converted to 0, but was unable to find mention of whitespace considered equal to false using Google.
Why is this? Is there some good reading on the subject besides digging into the ECMAScript spec?
This page provides a good summary of the rules.
Going by those rules, the '\t\n ' is converted in a number (Number('\t\n') ==> 0), and the false is converted into a number (Number(false) ==> 0), and hence the two are equal.
Alex's answer is also a good breakdown of the particular case of '\t\n ' == false.
An important distinction is that '\t\n ' is not falsy. For example:
if ('\t\n ') alert('not falsy'); // will produce the alert
whitespace == false; // true
Type coercion, love it or hate it.
Digging into the ES5 spec atm. There really isn't any other good way apart from reading what someone else dug out of the ES5 spec.
If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
new Number(false) == " "; // true
Booleans get converted to 0 or 1. The reason this is the case is that whitespace == 0
And if you really want to know about new Number(" ") then read this 9.3.1 in the ES5 spec.
The important line is :
The MV of StringNumericLiteral ::: StrWhiteSpace is 0.
Here is how I think it works, based on my readings and Raynos' answer (as well as the other latecomers to the party).
// Original expression
lg('\t\n ' == false);
// Boolean false is converted to Number
lg('\t\n ' == new Number(false));
// Boolean has been converted to 0
lg('\t\n ' == 0);
// Because right hand operand is 0, convert left hand to Number
lg(new Number('\t\n ') == 0);
// Number of whitespace is 0, and 0 == 0
lg(0 == 0);
jsFiddle.
Please let me know if I have something wrong.
I think the process can be described in a recursive function. (Imagining we live in a world where JavaScript only has the strict equality operator.)
function equals(x, y) {
if (typeof y === "boolean") {
return equals(x, +y);
}
else if (typeof x === "string") {
return +x === y;
}
}
A StringNumericLiteral that is empty or contains only white space is converted to +0.

Categories

Resources