Javascript Code
I am concacting two variables and comparing with a string
Why the alert is true? Why it is not coercing??
var str1 = "2";
var str2 = "3";
var res = str1 + str2 // return 23
console.log(res) // 23
console.log("100") // 100
alert(res > "100") // alerts true instead of false
The value in res is a string. In strings "23" is greater than "100" (looking at the first character).
To further answer your question "why isn't javascript coercing" I'd like to quote a comment from James Thorpe
"Both sides are strings - there is nothing to coerce"
Here's a code example.
console.log (23 > "100") // false
console.log ("23" > "100") // true
First console.log compares number with string - javascript coerces.
Second console.log compares string with string - nothing to coerce
Alert is true because '23' is lexicographically greater than '100' ('2' > '1').
You can use parseInt to convert strings to numbers:
alert(parseInt(res) > 100);
Because you are comparing strings. "100" is lower then "23" because "1"<"2".
You should parse to int if you want numerical comparison, as shown in #jh314 answer.
You can temporarily change the string to their number representation i.e, 23 and 100 and use the comparison operator. Either prefix the values with + to change them to numeric value or use parseInt():
var str1 = "2";
var str2 = "3";
var res = str1 + str2 // return 23
console.log(res) // 23
console.log("100") // 100
alert(+res > +"100")
The value of res is "23" not 23. That means it's a string and therefore when you alert the comparison it compares the first digit of each, 2 > 1 which is true.
As for “why is it not coercing?” - because both operands are strings in both cases, and because both + and > are valid operations on strings.
(Using - (subtract) would cause implicit coercion to number because it doesn’t make sense for strings, but concatenation and addition use the same operator. Welcome to JavaScript!)
Your alert is comparing a string and a string.
Try: alert(res > 100)
Related
1) Why the 155100 is a number here? Just like 255 would be if var s = 155;.
2) Why the 155100 is still a number even if var n = "100"; ?
3) Where and why is var res converted to a number?
What am I missing here?
var s = "155";
var n = 100;
var res = s + n;
document.write(res + "<hr>");
if ( isNaN(res) ) {
document.write("It is not a number");
}
if ( !isNaN(res) ) {
document.write("It is a number");
}
<html>
<head>
<title>stackoverflow.com</title>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
Thank you so much!
To your questions:
Why the 155100 is a number here? Just like 255 would be if var s = 155;?
It is a string, but when passed to isNaN, that function coerces it to a number and then returns whether that coercion resulted in NaN.
Why the 155100 is still a number even if var n = "100";?
See above. It is not.
Where and why is var res converted to a number?
It is not -- it remains a string.
But as documented on MDN:
When the argument to the isNaN function is not of type Number, the value is first coerced to a Number.
Notes
To check if a variable is of the Number type:
if (typeof res === 'number')
To convert a string to a number, one of these:
i = +res;
i = Number(res);
If you want to only check the start of a string, and not fail if any subsequent characters are not numeric (like 123.45abc), then use:
i = parseFloat(res);
If your interest is only in integers, you can use parseInt, preferably with the second argument to indicate the base. Like with parseFloat, it does not return NaN as soon as the first character passes the test:
i = parseInt(res, 10);
See the MDN link here.
isNaN(res) ---> will be false because 155100 is numeric
typeof res ---> string
Go ahead - try it in your Chrome console right now.
typeof "155100"
isNaN will always return false for a string value regardless of whether or not it can be parsed into a valid number. In order to check if your string is a valid number, you can parse it with parseInt and check if the result is NaN:
var s = "155";
var n = 100;
var res = s + n;
document.write(res + "<hr>");
if ( isNaN(parseInt(res)) ) {
document.write("It is not a number");
} else {
document.write("It is a number");
}
Note: parseInt will only return NaN if the first character cannot be converted to a number. MDN has a "stricter" version here that returns NaN if any part of the string cannot be converted .
JavaScript is a language based upon loose type-interpretation, instead of implicitly requiring type declaration or throwing an error else-wise;
When JavaScript gets a something in quotes, it determines it to be a string; the + operator, with the type now being String, is understood by JavaScript in this context as a string concatenater (concatenation is the combination of two or more things things) and so it happily appends the two together.
Here, you need to do what is known as Type Casting or Type Throwing where you throw(or cast) something into a different type. This is necessary here so that your + operator will behave as you desire
For Example:
var str = "3.14";
var num = new Number(str);
The new keyword is optional, but is recommended for source clarity and readability.
I have JS code to validate a Zip Code: 10 numeric chars with a dash in the 6th position (e.g., 12345-6789). I verify that both parts are numbers using !isNaN.
if (valSize == 10) {
var numVal1 = new Number(newVal.substring(0, 4));
var numVal2 = new Number(newVal.substring(6, 9));
if (newVal.charAt(5) == '-' && !isNaN(numVal1) && !isNaN(numVal2)) {
return newVal;
}
}
throw "Incorrect format";
This mostly works, but for some reason the following value goes through, and an error is NOT returned:
12345-678a
Why is !IsNaN(substring(6,9)) allowed to pass in this case?
String.substring function signature is:
str.substring(indexA[, indexB])
indexA
An integer between 0 and the length of the string, specifying the
offset into the string of the first character to include in the
returned substring.
indexB
Optional. An integer between 0 and the length of the string, which
specifies the offset into the string of the first character NOT to
include in the returned substring.
So you have:
"12345-678a".substring(0,4) // 1234
"12345-678a".substring(6,9) // 678
So either correct the indices:
"12345-678a".substring(0,5) // 12345
"12345-678a".substring(6) // 678a
Or use String.substr.
Or use regex (recommended) since your current code, after fixing, would happily accept 12.45-67.8, +1234--678 and 12e45-6e-9. All you need to do is this:
/^\d{5}-\d{4}$/.test("12345-678a") // false
/^\d{5}-\d{4}$/.test("12.45-67.8") // false
/^\d{5}-\d{4}$/.test("12345-6789") // true
Would a regex not be the more proper test?
/\d{5}-\d{4}/.test('12345-1234')
true
/\d{5}-\d{4}/.test('12345-123a')
false
newVal.substring(6,9) in the case of the string "12345-678a" would return "678" which is a number. So there should not be an error thrown.
I have a very, very simple logical test of the number of licenses a customer has purchased vs. the number they have used:
else if(utype == "3"){
var tech_lic = $("#technician_lic").val();
console.log('tech lic = ' + tech_lic)
var tech_allow = $("#technician_lic_allow").val();
console.log('tech allow = ' + tech_allow)
if(tech_lic >= tech_allow)
{
alert("You must purchase more licenses to create this Technician");
return false;
}
I threw in the console.log statements trying to debug this - normally they aren't there.
Console.log when I click "add" button:
tech lic = 4 application.js:262
tech allow = 100 application.js:264
Then we hit "You must purchase more licenses" alert in the window.
WHAT THE HECK?
How can 4 >= 100 evaluate true?
Because .val returns a string. '4' is indeed greater than or equal to '100'. Cast the values to numbers first (if you know that they are always numbers for the purposes of this comparison).
if (+tech_lic >= +tech_allow)
You are evaluating them as strings, so "4" IS greater than "100".
You will need to cast them as integers before comparison:
var tech_lic = parseInt($("#technician_lic").val(), 10);
var tech_allow = parseInt($("#technician_lic_allow").val(), 10);
The string "4" is greater than "100", whereas the number 4 is less than 100.
It's not that 4 >= 100 is true, it's that "4" >= "100" is true.
The values that you get are strings, so they will be compared lexically, not numerically.
Parse the values into numbers:
var tech_lic = parseInt($("#technician_lic").val(), 10);
var tech_allow = parseInt($("#technician_lic_allow").val(), 10);
Do this way:-
if(Number(tech_lic) >= Number(tech_allow))
{
// Do your stuff
}
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);
I want to check if a string contains only digits. I used this:
var isANumber = isNaN(theValue) === false;
if (isANumber){
..
}
But realized that it also allows + and -. Basically, I want to make sure an input contains ONLY digits and no other characters. Since +100 and -5 are both numbers, isNaN() is not the right way to go.
Perhaps a regexp is what I need? Any tips?
how about
let isnum = /^\d+$/.test(val);
string.match(/^[0-9]+$/) != null;
String.prototype.isNumber = function(){return /^\d+$/.test(this);}
console.log("123123".isNumber()); // outputs true
console.log("+12".isNumber()); // outputs false
If you want to even support for float values (Dot separated values) then you can use this expression :
var isNumber = /^\d+\.\d+$/.test(value);
Here's another interesting, readable way to check if a string contains only digits.
This method works by splitting the string into an array using the spread operator, and then uses the every() method to test whether all elements (characters) in the array are included in the string of digits '0123456789':
const digits_only = string => [...string].every(c => '0123456789'.includes(c));
console.log(digits_only('123')); // true
console.log(digits_only('+123')); // false
console.log(digits_only('-123')); // false
console.log(digits_only('123.')); // false
console.log(digits_only('.123')); // false
console.log(digits_only('123.0')); // false
console.log(digits_only('0.123')); // false
console.log(digits_only('Hello, world!')); // false
Here is a solution without using regular expressions:
function onlyDigits(s) {
for (let i = s.length - 1; i >= 0; i--) {
const d = s.charCodeAt(i);
if (d < 48 || d > 57) return false
}
return true
}
where 48 and 57 are the char codes for "0" and "9", respectively.
This is what you want
function isANumber(str){
return !/\D/.test(str);
}
in case you need integer and float at same validation
/^\d+\.\d+$|^\d+$/.test(val)
function isNumeric(x) {
return parseFloat(x).toString() === x.toString();
}
Though this will return false on strings with leading or trailing zeroes.
Well, you can use the following regex:
^\d+$
if you want to include float values also you can use the following code
theValue=$('#balanceinput').val();
var isnum1 = /^\d*\.?\d+$/.test(theValue);
var isnum2 = /^\d*\.?\d+$/.test(theValue.split("").reverse().join(""));
alert(isnum1+' '+isnum2);
this will test for only digits and digits separated with '.' the first test will cover values such as 0.1 and 0 but also .1 ,
it will not allow 0. so the solution that I propose is to reverse theValue so .1 will be 1. then the same regular expression will not allow it .
example :
theValue=3.4; //isnum1=true , isnum2=true
theValue=.4; //isnum1=true , isnum2=false
theValue=3.; //isnum1=flase , isnum2=true
Here's a Solution without using regex
const isdigit=(value)=>{
const val=Number(value)?true:false
console.log(val);
return val
}
isdigit("10")//true
isdigit("any String")//false
If you use jQuery:
$.isNumeric('1234'); // true
$.isNumeric('1ab4'); // false
If you want to leave room for . you can try the below regex.
/[^0-9.]/g
c="123".match(/\D/) == null #true
c="a12".match(/\D/) == null #false
If a string contains only digits it will return null