Compare x ='' and x = 0 in Javascript - javascript

I have the following:
var a = 0;
if (Number(a) != '')
{
alert('hi');
}
I never get the alert even though a is not empty, it is 0 and I need this value for numeric calculations.enter code here
What's going on here?

The != operator does type conversion if needed, so '' is converted to the numeric value 0.
You can use the !== operator to avoid the type conversion:
var a = 0;
if (Number(a) !== '')
{
alert('hi');
}

try the following
var a = 0;
if (Number(a) !== '') {
alert('hi');
}
If you compare two values using == or != operator, javascript type-coerces both of them and then compares. On the contrary, if you use === instead of == (or !== instead of !=), type coercion does not happen.

You are comparing 0 != 0 which will always be false.
The main issue is that the implicit cast here is causing '' to become 0. This can be easily verified.
alert(Number(''));//0
But why does this happen? It is defined behavior in the Language Specification as seen at
9.3.1 ToNumber Applied to the String Type
http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1
The conversion of a String to a Number value is similar overall to the determination of the Number value for a numeric literal (see 7.8.3), but some of the details are different, so the process for converting a String numeric literal to a value of Number type is given here in full. This value is determined in two steps: first, a mathematical value (MV) is derived from the String numeric literal; second, this mathematical value is rounded as described below.
The MV of StringNumericLiteral ::: [empty] is 0.
This is why the value of implicitly converting an empty string to a number is 0.
Going forward, it would make more sense to check for a number by using isNaN to ensure that a number was entered by the user or is present in the variable.
var a = 0;
if (!isNaN(a))
{
alert('a is a number');
}

use the !== operator to avoid type conversion

Related

A javascript statement that I haven't seen before

I am inspecting some Javascript code written in UnderscoreJS. In this, there are quite a few instances of JS code being written like this:
if(length === +length){ //do something}
or
if(length !== +length){ //do something }
What exactly does this compute to? I have never seen this before.
if (length === +length)
It makes sure that the length is actually a numeric value.
Two things to understand here,
The Strict equality operator, will evaluate to true only when the objects are the same. In JavaScript, the numbers and strings are immutables. So, when you compare two numbers, the Number values will be compared.
Unary + operator will try to get the numeric value of any object. If the object is already of type Number, it will not make any changes and return the object as it is.
In this case, if length is actually a number in string format, lets say "1", the expression
"1" == +"1"
will evaluate to be true, because "1" is coerced to numeric 1 internally and compared. But
"1" === +"1"
which will be transformed to
"1" === 1
and that will not undergo coercion and since the types are different, === will evaluate to false. And if length is of any other type, === will straight away return false, as the right hand side is a number.
You can think of this check as a shorthand version of this
if (Object.prototype.toString.call(length) === "[object Number]")
It is a way of testing whether a value is numeric. See this for example:
> length="string"
> length === +length
false
> length=2
> length === +length
true
The unary + converts the variable length to the Number type, so if it was already numeric then the identity will be satisfied.
The use of the identity operator === rather than the equality operator == is important here, as it does a strict comparison of both the value and the type of the operands.
Perhaps a more explicit (but slightly longer to write) way of performing the same test would be to use:
typeof length === "number"

Why javascript treats 0 equal to empty string? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Implied string comparison, 0='', but 1='1'
Executing the following case in javascript, I get 0 equal to '' (an empty string)
var a = 0;
var b = '';//empty string
if(a==b){
console.log('equal');//this is printed in console
}else{
console.log('not equal');
}
Could anyone guide that what is the reason behind this?
Quoting the doc (MDN):
Equal (==)
If the two operands are not of the same type, JavaScript converts the
operands then applies strict comparison. If either operand is a number
or a boolean, the operands are converted to numbers if possible; else
if either operand is a string, the other operand is converted to a
string if possible.
As a operand type here is Number, b gets converted to Number as well. And Number('') evaluates to 0.
This can be quite surprising sometimes. Consider this, for example:
console.log(0 == '0'); // true
console.log(0 == ''); // true
console.log('' == '0'); // O'RLY?
... or this:
console.log(false == undefined); // false
console.log(false == null); // false
console.log(null == undefined); // fal.... NO WAIT!
...and that's exactly why it's almost always recommended to use === (strict equality) operator instead.
0, "" (Empty String), false all technically have the same value, when typecasted. If you need to strictly treat them, you can use ===.
It is the same with similar programming languages, like PHP.
var a = 0;
var b = ''; //empty string
if(a == b){
console.log('equal'); //this is printed in console
}else{
console.log('not equal');
}
To make a strict comparison:
if(a === b){
console.log('equal');
}else{
console.log('not equal'); //this is printed in console
}
== operator in javascript don't compare types so 0=='' === true (because as a number string '' evaluates to 0) or 0==false === true (because bool false evaluates to 0) to compare types to you can use === operator.
Here you'll find useful information about comparison.
Javascript automatically converts variables of different types for comparison. That's a common feature in non-strictly typed languages.
If you need to compare variables and check the type, use the === operator.
In most programming language(including javascript) ""(string), 0(integer), \x0(null) losely mean the same thing: "empty". What's happening is your javascript engine finds "" == 0 false, due to the == it converts 0 to an integer. Again this is false, so it converts 0 to null which is false, so then it converts 0 to an empty string. (Not sure if this is the correct order of conversion). To make the condition "exact" match(no conversion) use === inplace of ==
== does typecasting. Always use ===.
In your example, the empty string of b is being converted to 0. So both a and b are the same.
Because empty string represented as number is zero. If you compare apples and oranges you should think of how your particular orange would look if it were an apple.
Because of coercion. It is usually a better idea to use === for comparisons in JavaScript.
Because == checks value equality so false, 0 and empty strings are equals. Use identity check ===.

Convert an entire String into an Integer in JavaScript

I recently ran into a piece of code very much like this one:
var nHours = parseInt(txtHours);
if( isNaN(nHours)) // Do something
else // Do something else with the value
The developer who wrote this code was under the impression that nHours would either be an integer that exactly matched txtHours or NaN. There are several things wrong with this assumption.
First, the developer left of the radix argument which means input of "09" would result in a value of 0 instead of 9. This issue can be resolved by adding the radix in like so:
var nHours = parseInt(txtHours,10);
if( isNaN(nHours)) // Do something
else // Do something else with the value
Next, input of "1.5" will result in a value of 1 instead of NaN which is not what the developer expected since 1.5 is not an integer. Likewise a value of "1a" will result in a value of 1 instead of NaN.
All of these issues are somewhat understandable since this is one of the most common examples of how to convert a string to an integer and most places don't discuss these cases.
At any rate it got me thinking that I'm not aware of any built in way to get an integer like this. There is Number(txtHours) (or +txtHours) which comes closer but accepts non-integer numbers and will treat null and "" as 0 instead of NaN.
To help the developer out I provided the following function:
function ConvertToInteger(text)
{
var number = Math.floor(+text);
return text && number == text ? number : NaN;
}
This seems to cover all the above issues. Does anyone know of anything wrong with this technique or maybe a simpler way to get the same results?
Here, that's what I came up with:
function integer(x) {
if (typeof x !== "number" && typeof x !== "string" || x === "") {
return NaN;
} else {
x = Number(x);
return x === Math.floor(x) ? x : NaN;
}
}
(Note: I updated this function to saveguard against white-space strings. See below.)
The idea is to only accept arguments which type is either Number or String (but not the empty string value). Then a conversion to Number is done (in case it was a string), and finally its value is compared to the floor() value to determine if the number is a integer or not.
integer(); // NaN
integer(""); // NaN
integer(null); // NaN
integer(true); // NaN
integer(false); // NaN
integer("1a"); // NaN
integer("1.3"); // NaN
integer(1.3); // NaN
integer(7); // 7
However, the NaN value is "misused" here, since floats and strings representing floats result in NaN, and that is technically not true.
Also, note that because of the way strings are converted into numbers, the string argument may have trailing or leading white-space, or leading zeroes:
integer(" 3 "); // 3
integer("0003"); // 3
Another approach...
You can use a regular expression if the input value is a string.
This regexp: /^\s*(\+|-)?\d+\s*$/ will match strings that represent integers.
UPDATED FUNCTION!
function integer(x) {
if ( typeof x === "string" && /^\s*(\+|-)?\d+\s*$/.test(x) ) {
x = Number(x);
}
if ( typeof x === "number" ) {
return x === Math.floor(x) ? x : NaN;
}
return NaN;
}
This version of integer() is more strict as it allows only strings that follow a certain pattern (which is tested with a regexp). It produces the same results as the other integer() function, except that it additionally disregards all white-space strings (as pointed out by #CMS).
Updated again!
I noticed #Zecc's answer and simplified the code a bit... I guess this works, too:
function integer(x) {
if( /^\s*(\+|-)?\d+\s*$/.test(String(x)) ){
return parseInt(x, 10);
}
return Number.NaN;
}
It probaly isn't the fastest solution (in terms of performance), but I like its simplicity :)
Here's my attempt:
function integer(x) {
var n = parseFloat(x); // No need to check typeof x; parseFloat does it for us
if(!isNaN(n) && /^\s*(\+|-)?\d+\s*$/.test(String(x))){
return n;
}
return Number.NaN;
}
I have to credit Šime Vidas for the regex, though I would get there myself.
Edit: I wasn't aware there was a NaN global. I've always used Number.NaN.
Live and learn.
My Solution involves some cheap trick. It based on the fact that bit operators in Javascript convert their operands to integers.
I wasn't quite sure if strings representing integers should work so here are two different solutions.
function integer (number) {
return ~~number == number ? ~~number : NaN;
}
function integer (number) {
return ~~number === number ? ~~number : NaN;
}
The first one will work with both integers as strings, the second one won't.
The bitwise not (~) operator will convert its operand to an integer.
This method fails for integers bigger which can't be represented by the 32bit wide representation of integers (-2147483647 .. 2147483647).
You can first convert a String to an Integer, and then back to a String again. Then check if first and second strings match.
Edit: an example of what I meant:
function cs (stringInt) {
var trimmed = stringInt.trim(); // trim original string
var num = parseInt(trimmed, 10); // convert string to integer
newString = num + ""; // convert newly created integer back to string
console.log(newString); // (works in at least Firefox and Chrome) check what's new string like
return (newString == trimmed); // if they are identical, you can be sure that original string is an integer
}
This function will return true if a string you put in is really an integer. It can be modified if you don't want trimming. Using leading zeroes will fail, but, once again, you can get rid of them in this function if you want. This way, you don't need to mess around with NaN or regex, you can easily check validity of your stringified integer.

Why does isNaN(" ") (string with spaces) equal false?

In JavaScript, why does isNaN(" ") evaluate to false, but isNaN(" x") evaluate to true?
I’m performing numerical operations on a text input field, and I’m checking if the field is null, "", or NaN. When someone types a handful of spaces into the field, my validation fails on all three, and I’m confused as to why it gets past the isNaN check.
JavaScript interprets an empty string as a 0, which then fails the isNAN test. You can use parseInt on the string first which won't convert the empty string to 0. The result should then fail isNAN.
You may find this surprising or maybe not, but here is some test code to show you the wackyness of the JavaScript engine.
document.write(isNaN("")) // false
document.write(isNaN(" ")) // false
document.write(isNaN(0)) // false
document.write(isNaN(null)) // false
document.write(isNaN(false)) // false
document.write("" == false) // true
document.write("" == 0) // true
document.write(" " == 0) // true
document.write(" " == false) // true
document.write(0 == false) // true
document.write(" " == "") // false
so this means that
" " == 0 == false
and
"" == 0 == false
but
"" != " "
Have fun :)
To understand it better, please open Ecma-Script spec pdf on page 43 "ToNumber Applied to the String Type"
if a string has a numerical syntax, which can contain any number of white-space characters, it can be converted to Number type. Empty string evaluates to 0. Also the string 'Infinity' should give
isNaN('Infinity'); // false
Try using:
alert(isNaN(parseInt(" ")));
Or
alert(isNaN(parseFloat(" ")));
From MDN reason for the issue you are facing
When the argument to the isNaN function is not of type Number, the value is first coerced to a Number. The resulting value is then tested to determine whether it is NaN.
You may want to check the following comprehensive answer which covers the NaN comparison for equality as well.
How to test if a JavaScript variable is NaN
I think it's because of Javascript's typing: ' ' is converted to zero, whereas 'x' isn't:
alert(' ' * 1); // 0
alert('x' * 1); // NaN
The Not-Entirely-Correct Answer
Antonio Haley's highly upvoted and accepted answer here makes a wrong assumption that this process goes through JavaScript's parseInt function:
You can use parseInt on the string ... The result should then fail isNAN.
We can easily disprove this statement with the string "123abc":
parseInt("123abc") // 123 (a number...
isNaN("123abc") // true ...which is not a number)
With this, we can see that JavaScript's parseInt function returns "123abc" as the number 123, yet its isNaN function tells us that "123abc" isn't a number.
The Correct Answer
ECMAScript-262 defines how the isNaN check works in section 18.2.3.
18.2.3 isNaN (Number)
The isNaN function is the %isNaN% intrinsic object. When the isNaN function is called with one argument number, the following steps are taken:
Let num be ? ToNumber(number).
If num is NaN, return true.
Otherwise, return false.
The ToNumber function it references is also defined in ECMAScript-262's section 7.1.3. In here, we get told how JavaScript handles Strings which are passed in to this function.
The first example given in the question is a string containing nothing but white space characters. This section states that:
A StringNumericLiteral that is empty or contains only white space is converted to +0.
The " " example string is therefore converted to +0, which is a number.
The same section also states:
If the grammar cannot interpret the String as an expansion of StringNumericLiteral, then the result of ToNumber is NaN.
Without quoting all of the checks contained within that section, the " x" example given in the question falls into the above condition as it cannot be interpreted as a StringNumericLiteral. " x" is therefore converted to NaN.
If you would like to implement an accurate isNumber function, here is one way to do it from Javascript: The Good Parts by Douglas Crockford [page 105]
var isNumber = function isNumber(value) {
return typeof value === 'number' &&
isFinite(value);
}
The function isNaN("") performs a String to Number type coercion
ECMAScript 3-5 defines the following return values for the typeof operator:
undefined
object (null, objects, arrays)
boolean
number
string
function
Better to wrap our test in a function body:
function isNumber (s) {
return typeof s == 'number'? true
: typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
: (typeof s).match(/object|function/)? false
: !isNaN(s)
}
This function is not intented to test variable type, instead it tests the coerced value. For instance, booleans and strings are coerced to numbers, so perhaps you may want to call this function as isNumberCoerced()
if there's no need to test for types other than string and number, then the following snippet might be used as part of some condition:
if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
alert("s is a number")
NaN !== "not a number"
NaN is a value of Number Type
this is a definition of isNaN() in ECMAScript
1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.
Try to convert any value to Number.
Number(" ") // 0
Number("x") // NaN
Number(null) // 0
If you want to determine if the value is NaN, you should try to convert it to a Number value firstly.
I suggest you to use the following function if you really want a proper check if it is an integer:
function isInteger(s)
{
return Math.ceil(s) == Math.floor(s);
}
That isNaN(" ") is false is part of the confusing behavior of the isNaN global function due to its coercion of non-numbers to a numeric type.
From MDN:
Since the very earliest versions of the isNaN function specification, its behavior for non-numeric arguments has been confusing. When the argument to the isNaN function is not of type Number, the value is first coerced to a Number. The resulting value is then tested to determine whether it is NaN. Thus for non-numbers that when coerced to numeric type result in a valid non-NaN numeric value (notably the empty string and boolean primitives, which when coerced give numeric values zero or one), the "false" returned value may be unexpected; the empty string, for example, is surely "not a number."
Note also that with ECMAScript 6, there is also now the Number.isNaN method, which according to MDN:
In comparison to the global isNaN() function, Number.isNaN() doesn't suffer the problem of forcefully converting the parameter to a number. This means it is now safe to pass values that would normally convert to NaN, but aren't actually the same value as NaN. This also means that only values of the type number, that are also NaN, return true.
Unfortunately:
Even the ECMAScript 6 Number.isNaN method has its own issues, as outlined in the blog post - Fixing the ugly JavaScript and ES6 NaN problem.
The isNaN function expects a Number as its argument, so arguments of any other type (in your case a string) will be converted to Number before the actual function logic is performed. (Be aware that NaN is also a value of type Number!)
Btw. this is common for all built-in functions - if they expect an argument of a certain type, the actual argument will be converted using the standard conversion functions. There are standard conversions between all the basic types (bool, string, number, object, date, null, undefined.)
The standard conversion for String to Number can be invoked explicit with Number(). So we can see that:
Number(" ") evaluates to 0
Number(" x") evaluates to NaN
Given this, the result of the isNaN function is completely logical!
The real question is why the standard String-to-Number conversion works like it does. The string-to-number conversion is really intended to convert numeric strings like "123" or "17.5e4" to the equivalent numbers. The conversion first skips initial whitespace (so " 123" is valid) and then tries to parse the rests as a number. If it is not parseable as a number ("x" isn't) then the result is NaN. But there is the explicit special rule that a string which is empty or only whitespace is converted to 0. So this explains the conversion.
Reference: http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1
I'm not sure why, but to get around the problem you could always trim whitespace before checking. You probably want to do that anyway.
I wrote this quick little function to help solve this problem.
function isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
It simply checks for any characters that aren't numeric (0-9), that aren't '-' or '.', and that aren't undefined, null or empty and returns true if there's no matches. :)
As other explained the isNaN function will coerce the empty string into a number before validating it, thus changing an empty string into 0 (which is a valid number).
However, I found that the parseInt function will return NaN when trying to parse an empty string or a string with only spaces. As such the following combination seems to be working well:
if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');
This check will work for positive numbers, negative numbers and numbers with a decimal point, so I believe it covers all common numerical cases.
This function seemed to work in my tests
function isNumber(s) {
if (s === "" || s === null) {
return false;
} else {
var number = parseInt(s);
if (number == 'NaN') {
return false;
} else {
return true;
}
}
}
What about
function isNumberRegex(value) {
var pattern = /^[-+]?\d*\.?\d*$/i;
var match = value.match(pattern);
return value.length > 0 && match != null;
}
The JavaScript built-in isNaN function, is - as should be expected by default - a "Dynamic Type Operator".
Therefore all values which (during the DTC process) may yield a simple true | false such as "", " ", " 000", cannot be NaN.
Meaning that the argument supplied will first undergo a conversion as in:
function isNaNDemo(arg){
var x = new Number(arg).valueOf();
return x != x;
}
Explanation:
In the top line of the function body, we are (first) trying to successfully convert the argument into a number object. And (second), using the dot operator we are - for our own convenience - immediately stripping off, the primitive value of the created object.
In the second line, we are taking the value obtained in the previous step, and the advantage of the fact that NaN is not equal to anything in the universe, not even to itself, e.g.: NaN == NaN >> false to finally compare it (for inequality) with itself.
This way the function return will yield true only when, and only if, the supplied argument-return, is a failed attempt of conversion to a number object, i.e., a not-a-number number; e.g., NaN.
isNaNstatic( )
However, for a Static Type Operator - if needed and when needed - we can write a far simpler function such as:
function isNaNstatic(x){
return x != x;
}
And avoid the DTC altogether so that if the argument is not explicitly a NaN number, it will return false. Wherefore, testing against the following:
isNaNStatic(" x"); // will return false because it's still a string.
However:
isNaNStatic(1/"x"); // will of course return true. as will for instance isNaNStatic(NaN); >> true.
But contrary to isNaN, the isNaNStatic("NaN"); >> false because it (the argument) is an ordinary string.
p.s.:
The static version of isNaN can be very useful in modern coding scenarios. And it may very well be one of the main reasons I took my time for posting this.
Regards.
isNAN(<argument>) is a function to tell whether given argument is illegal number.
isNaN typecasts the arguments into Number type. If you want to check if argument is Numeric or not? Please use $.isNumeric() function in jQuery.
That is, isNaN(foo) is equivalent to isNaN(Number(foo))
It accepts any strings having all numerals as numbers for obvious reasons. For ex.
isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true
I use this
function isNotANumeric(val) {
if(val.trim && val.trim() == "") {
return true;
} else {
return isNaN(parseFloat(val * 1));
}
}
alert(isNotANumeric("100")); // false
alert(isNotANumeric("1a")); // true
alert(isNotANumeric("")); // true
alert(isNotANumeric(" ")); // true
When checking if certain string value with whitespace or " "is isNaN maybe try to perform string validation, example :
// value = "123 "
if (value.match(/\s/) || isNaN(value)) {
// do something
}
I find it convenient to have a method specific to the Number class (since other functions that do conversions like parseInt have different outputs for some of these values) and use prototypal inheritance.
Object.assign(Number.prototype, {
isNumericallyValid(num) {
if (
num === null
|| typeof num === 'boolean'
|| num === ''
|| Number.isNaN(Number(num))
) {
return false;
}
return true;
}
});
I use the following.
x=(isNaN(parseFloat(x)))? 0.00 : parseFloat(x);
let isNotNumber = val => isNaN(val) || (val.trim && val.trim() === '');
console.log(isNotNumber(' '));
console.log(isNotNumber('1'));
console.log(isNotNumber('123x'));
console.log(isNotNumber('x123'));
console.log(isNotNumber('0'));
console.log(isNotNumber(3));
console.log(isNotNumber(' x'));
console.log(isNotNumber('1.23'));
console.log(isNotNumber('1.23.1.3'));
if(!isNotNumber(3)){
console.log('This is a number');
}

Getting a integer value from a textbox, how to check if it's NaN or null etc?

I am pulling a value via JavaScript from a textbox. If the textbox is empty, it returns NaN. I want to return an empty string if it's null, empty, etc.
What check do I do? if(NAN = tb.value)?
Hm, something is fishy here.
In what browser does an empty textbox return NaN? I've never seen that happen, and I cannot reproduce it.
The value of a text box is, in fact a string. An empty text box returns an empty string!
Oh, and to check if something is NaN, you should use:
if (isNaN(tb.value))
{
...
}
Note: The isNaN()-function returns true for anything that cannot be parsed as a number, except for empty strings. That means it's a good check for numeric input (much easier than regexes):
if (tb.value != "" && !isNaN(tb.value))
{
// It's a number
numValue = parseFloat(tb.value);
}
You can also do it this way:
var number = +input.value;
if (input.value === "" || number != number)
{
// not a number
}
NaN is equal to nothing, not even itself.
if you don't like to use + to convert from String to Number, use the normal parseInt, but remember to always give a base
var number = parseInt(input.value, 10)
otherwise "08" becomes 0 because Javascript thinks it's an octal number.
Assuming you have a reference to the input text box:
function getInteger(input) {
if(!input || !input.value) return "";
var val = parseInt(input.value, 10);
if(isNaN(val)) return "";
else return val;
}
One thing you could do is a regex check on the value of the textbox and make sure it fits the format of an accepted number, and then if it fits the format perform your process, otherwise return an empty string.
Edit: This is an example from some code I have in front of me (might not be the best regular expression):
var anum=/(^\d+$)/;
if (!anum.test(document.getElementById("<%=txtConceptOrderValue.ClientID %>").value))
{
alert("Order Value must be a valid integer");
document.getElementById("<%=txtConceptOrderValue.ClientID %>").focus();
return false;
}
Edit 2: I should also note that I am using ASP.NET which is why I have the slightly funky way of accessing the textbox. In your regular JavaScript case it may not be as cluttered.

Categories

Resources