looking for alternative way to do isNaN test - javascript

I'm looking for an alternative way to do an isNaN test
My original code looked like this. The code works, but I noticed that num1 changes type, which is ugly
// example 1: num1 changes type
num1 = parseInt(str1, 10);
if isNaN(num1){num1=-1;}
I changed it to this, but this one uses duplicate code
// example 2: duplicate code
if (isNaN(parseInt(str1,10))){num1=-1;}
else {num1=parseInt(str1,10);}
At first I was thinking about adding an extra variable to store parseInt(str1,10) but that variable will change type, too and is therefore in effect the same as example 1.
Is there an alternative to example 1 or 2?
by changes type I mean this
console.log(typeof(isNaN("123"))); // boolean
console.log(typeof(isNaN("abc"))); // boolean
console.log(typeof(parseInt("123", 10))); // number
console.log(typeof(parseInt("abc", 10))); // number
.
console.log(typeof(Number("123"))); // number
console.log(typeof(Number("abc"))); // number
console.log(Number("123")); // 123
console.log(Number("abc")); // NaN

First, I would suggest that parseInt() isn't the best choice. For example:
var x = parseInt("123hello world how are you today?", 10);
will set "x" to 123 and simply ignore the trailing garbage.
You could set up a functional way to do this, if you really wanted to avoid the intermediate temporary value:
function ifNumeric( s, f ) {
s = +s;
if (!isNaN(s)) f(s);
}
ifNumeric( someString, function( n ) { /* whatever, with "n" being a number */ } );
but that seems a little extreme. But anyway note that in that example the + operator is used to coerce the value of the variable to the "number" type. You could alternatively use the "Number" constructor, but not as a constructor:
var numeric = Number( someString );
Either of those will give you a NaN if the string isn't a completely valid number without trailing garbage.
edit — if you just want a safe "give me a number" converter:
function toNumber( value, ifGarbage ) {
value = +value;
return isNaN(value) ? ifGarbage : value;
}
var num1 = toNumber( str1, -1 );

Related

convert number to string returns empty if number 0

Trying to convert string to a number, works fine apart from when the number is zero it returns an empty string;
I understand 0 is false, but I just need a neat way of it returning the string "0"
I'm using:
const num = this.str ? this.str.toString() : '' ;
I even thought of using es6 and simply ${this.str} but that didn't work
Because 0 is "false-y" in JavaScript, as you've already figured out, you can't utilized it in a conditional. Instead, ask yourself what the conditional is really trying to solve.
Are you worried about null / undefined values? Perhaps this is better:
const num = (typeof this.str !== "undefined" && this.str !== null) ? this.str.toString() : "";
Odds are you really only care if this.str is a Number, and in all other cases want to ignore it. What if this.str is a Date, or an Array? Both Date and Array have a .toString() method, which means you may have some weird bugs crop up if one slips into your function unexpectedly.
So a better solution may be:
const num = (typeof this.str === "number") ? this.str.toString() : "";
You can also put your code in a try catch block
const num = ''
try {
num = this.str.toString();
} catch(e) {
// Do something here if you want.
}
Just adding to given answers - if you do:
x >> 0
you will convert anything to a Number
'7' >> 0 // 7
'' >> 0 // 0
true >> 0 // 1
[7] >> 0 // 7
It's a right shift bit operation. You can do magic with this in many real life cases, like described in this article.
In my case, the zero (number) that I wanted to converted to a string (which was the value of an option in a select element) was a value in an enum.
So I did this, since the enum was generated by another process and I could not change it:
let stringValue = '';
if (this.input.enumValue === 0) {
stringValue = '0';
} else {
stringValue = this.input.enumValue.toString();
}

Understanding underscore's implementation of isNaN

Taken from the underscore.js source:
_.isNaN = function(obj) {
return _.isNumber(obj) && obj != +obj;
};
Why did they do it this way? Is the above implementation equivalent to:
_.isNaN = function(obj) {
return obj !== obj;
};
If it is, why the "more complicated" version? If it is not, what are the behavioural differences?
_.isNaN(new Number(NaN)) returns true.
And that's by design.
var n = new Number(NaN);
console.log(_.isNaN(n), n!==n); // logs true, false
The host environment (e.g. web-browser environment) may introduce other values that aren't equal to themselves. The _.isNumber(obj) part makes sure that the input is a Number value, so that _.isNaN only returns true if the NaN value is passed.
If + is given before of any value with no preceding value to + , JavaScript engine will try to convert that variable to Number.If it is valid it will give you the Number else it will return NaN. For example
+ "1" // is equal to integer value 1
+ "a1" // will be NaN because "a1" is not a valid number
In above case
+"a1" != "a1" // true, so this is not a number, one case is satisfied
+"1" == "1" // true, so it is number
Another simple case would be, why the below expression give this output
console.log("Why I am " + typeof + "");
// returns "Why I am number"
Because +"" is 0.
If you want to check whether it is a number or not you could use the below function
function isNumber(a){
/* first method : */ return (+a == a);
/* second method : */ return (+(+a) >= 0);
// And so many other exists
}
Someone correct me if I am wrong somewhere..
I found one case for _.isNaN
It shows different result with the native one if you pass there an object
_.isNaN({}) => false
//but
isNaN({}) => true

Why using this method to return a function or value?

I'm just wondering why should I use this method to return a function :
clusters.prototype.get_local_storage_data = function(data_key) {
return +(this.localStorage.getItem(data_key) || 1);
};
What does the +() do there and why using that ? Is there a better way of returning the function or 1 if what the function gets is null ?
Using the + before a value forces that value to become a number. In the case above, the data key will be converted to a number (if it's found), or the number 1 will be returned. Either way, the result will be converted to a number.
+null; // 0
+"3.14"; // 3.14
+1; // 1
It's just ensuring that no matter what the output is, you will be returning a number.
The + is there to cast the result to a number -
typeof +"123" // "number"
The way it's implemented looks just fine, and doesn't need to be changed.
The + is just making sure the return value is a number or else 1 would be true and not the number one. It's a shortcut for:
Number( expression )

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);

type checking in javascript

How can I check if a variable is currently an integer type? I've looked for some sort of resource for this and I think the === operator is important, but I'm not sure how to check if a variable is an Integer (or an Array for that matter)
A variable will never be an integer type in JavaScript — it doesn't distinguish between different types of Number.
You can test if the variable contains a number, and if that number is an integer.
(typeof foo === "number") && Math.floor(foo) === foo
If the variable might be a string containing an integer and you want to see if that is the case:
foo == parseInt(foo, 10)
These days, ECMAScript 6 (ECMA-262) is "in the house". Use Number.isInteger(x) to ask the question you want to ask with respect to the type of x:
js> var x = 3
js> Number.isInteger(x)
true
js> var y = 3.1
js> Number.isInteger(y)
false
A number is an integer if its modulo %1 is 0-
function isInt(n){
return (typeof n== 'number' && n%1== 0);
}
This is only as good as javascript gets- say +- ten to the 15th.
isInt(Math.pow(2,50)+.1) returns true, as does
Math.pow(2,50)+.1 == Math.pow(2,50)
A clean approach
You can consider using a very small, dependency-free library like Issable. Solves all problems:
// at the basic level it supports primitives
let number = 10
let array = []
is(number).number() // returns true
is(array).number() // throws error
// so you need to define your own:
import { define } from 'issable'
// or require syntax
const { define } = require('issable')
define({
primitives: 'number',
nameOfTyping: 'integer',
toPass: function(candidate) {
// pre-ECMA6
return candidate.toFixed(0) === candidate.toString()
// ECMA6
return Number.isInteger(candidate)
}
})
is(4.4).custom('integer') // throws error
is(8).customer('integer') // returns true
If you make it a habit, your code will be much stronger. Typescript solves part of the problem but doesn't work at runtime, which is also important.
function test (string, boolean) {
// any of these below will throw errors to protect you
is(string).string()
is(boolean).boolean()
// continue with your code.
}
I know you're interested in Integer numbers so I won't re answer that but if you ever wanted to check for Floating Point numbers you could do this.
function isFloat( x )
{
return ( typeof x === "number" && Math.abs( x % 1 ) > 0);
}
Note: This MAY treat numbers ending in .0 (or any logically equivalent number of 0's) as an INTEGER. It actually needs a floating point precision error to occur to detect the floating point values in that case.
Ex.
alert(isFloat(5.2)); //returns true
alert(isFloat(5)); //returns false
alert(isFloat(5.0)); //return could be either true or false
Quite a few utility libraries such as YourJS offer functions for determining if something is an array or if something is an integer or a lot of other types as well. YourJS defines isInt by checking if the value is a number and then if it is divisible by 1:
function isInt(x) {
return typeOf(x, 'Number') && x % 1 == 0;
}
The above snippet was taken from this YourJS snippet and thusly only works because typeOf is defined by the library. You can download a minimalistic version of YourJS which mainly only has type checking functions such as typeOf(), isInt() and isArray(): http://yourjs.com/snippets/build/34,2
You may also have a look on Runtyper - a tool that performs type checking of operands in === (and other operations).
For your example, if you have strict comparison x === y and x = 123, y = "123", it will automatically check typeof x, typeof y and show warning in console:
Strict compare of different types: 123 (number) === "123" (string)
Try this code:
alert(typeof(1) == "number");

Categories

Resources