When to use parseInt - javascript

Which rule do I have to follow when extracting numbers out of DOM and calcluation with them? How does javascript knows that a value is a number or not? Should I always use parseInt?
Given following Code:
HTML
<div id="myvalue">5</div>
<div id="withParseInt"></div>
<div id="withoutParseInt"></div>
<div id="withoutParseIntButIncrement"></div>
JS & jQuery:
var value = $('#myvalue').text();
$('#withParseInt').text(parseInt(value) + 1);
$('#withoutParseInt').text(value + 1);
$('#withoutParseIntButIncrement').text(value++);
Gives following output:
5
6
51
5
Fiddle: http://jsfiddle.net/ytxKU/3/

The .text() method will always return a string. Some operators, like the + operator, are overloaded to perform both arithmetic and string operations. In the case of strings, it performs concatenation, hence the "51" result.
If you have a string and need to use a non-coercing operator, you will have to use parseInt (or some other method of converting to a number).
However, the * operator for example implicity performs this coercion, so you wouldn't need the parseInt call in that situation (see an updated fiddle for example).
Note that the increment ++ operator does coerce its operand, but you've used the postfix operator so it won't have any effect. Use the prefix operator and you can see it working:
$('#withoutParseIntButIncrement').text(++value);
So, to summarise:
// Parses string to number and adds 1
$('#withParseInt').text(parseInt(value) + 1);
// Coerces number 1 to string "1" and concatenates
$('#withoutParseInt').text(value + 1);
// Implicity coerces string to number, but after it's been inserted into the DOM
$('#withoutParseIntButIncrement').text(value++);
// Implicity coerces string to number, before it's been inserted into the DOM
$('#withoutParseIntButIncrement').text(++value);
// Implicity coerces to number
$('#withoutParseIntButMultiply').text(value * 2);
Side note: it's considered good practice to always pass the second argument (the radix) to parseInt. This ensures the number is parsed in the correct base:
parseInt(value, 10); // For base 10

One and only rule:
Every value that you retrieve from the DOM is a string.

Yes, you should always use parseInt() or Number() to be on the safe side. Otherwise Javascript will decide what to do with it
The value itself is a string
Using operator + will concatenate two strings
Using operator - will calculate the numerical difference
...

It's always good to use parseInt just to be on the safe side, especially as you can supply a second parameter for the numerical system to use.
By the way, in your final example it should be ++value if you want it to equal 6.

Related

Numeric conversion in JavaScript [duplicate]

How do parseInt() and Number() behave differently when converting strings to numbers?
Well, they are semantically different, the Number constructor called as a function performs type conversion and parseInt performs parsing, e.g.:
// parsing:
parseInt("20px"); // 20
parseInt("10100", 2); // 20
parseInt("2e1"); // 2
// type conversion
Number("20px"); // NaN
Number("2e1"); // 20, exponential notation
Also parseInt will ignore trailing characters that don't correspond with any digit of the currently used base.
The Number constructor doesn't detect implicit octals, but can detect the explicit octal notation:
Number("010"); // 10
Number("0o10") // 8, explicit octal
parseInt("010"); // 8, implicit octal
parseInt("010", 10); // 10, decimal radix used
And it can handle numbers in hexadecimal notation, just like parseInt:
Number("0xF"); // 15
parseInt("0xF"); //15
In addition, a widely used construct to perform Numeric type conversion, is the Unary + Operator (p. 72), it is equivalent to using the Number constructor as a function:
+"2e1"; // 20
+"0xF"; // 15
+"010"; // 10
typeof parseInt("123") => number
typeof Number("123") => number
typeof new Number("123") => object (Number primitive wrapper object)
first two will give you better performance as it returns a primitive instead of an object.
One minor difference is what they convert of undefined or null,
Number() Or Number(null) Or Number('') // returns 0
while
parseInt() Or parseInt(null) // returns NaN
Summary:
parseInt():
Takes a string as a first argument, the radix (An integer which is the base of a numeral system e.g. decimal 10 or binary 2) as a second argument
The function returns a integer number, if the first character cannot be converted to a number NaN will be returned.
If the parseInt() function encounters a non numerical value, it will cut off the rest of input string and only parse the part until the non numerical value.
If the radix is undefined or 0, JS will assume the following:
If the input string begins with "0x" or "0X", the radix is 16 (hexadecimal), the remainder of the string is parsed into a number.
If the input value begins with a 0 the radix can be either 8 (octal) or 10 (decimal). Which radix is chosen is depending on JS engine implementation. ES5 specifies that 10 should be used then. However, this is not supported by all browsers, therefore always specify radix if your numbers can begin with a 0.
If the input value begins with any number, the radix will be 10
Number():
The Number() constructor can convert any argument input into a number. If the Number() constructor cannot convert the input into a number, NaN will be returned.
The Number() constructor can also handle hexadecimal number, they have to start with 0x.
Example:
console.log(parseInt('0xF', 16)); // 15
// z is no number, it will only evaluate 0xF, therefore 15 is logged
console.log(parseInt('0xFz123', 16));
// because the radix is 10, A is considered a letter not a number (like in Hexadecimal)
// Therefore, A will be cut off the string and 10 is logged
console.log(parseInt('10A', 10)); // 10
// first character isnot a number, therefore parseInt will return NaN
console.log(parseInt('a1213', 10));
console.log('\n');
// start with 0X, therefore Number will interpret it as a hexadecimal value
console.log(Number('0x11'));
// Cannot be converted to a number, NaN will be returned, notice that
// the number constructor will not cut off a non number part like parseInt does
console.log(Number('123A'));
// scientific notation is allowed
console.log(Number('152e-1')); // 15.21
If you are looking for performance then probably best results you'll get with bitwise right shift "10">>0. Also multiply ("10" * 1) or not not (~~"10"). All of them are much faster of Number and parseInt.
They even have "feature" returning 0 for not number argument.
Here are Performance tests.
I found two links of performance compare among several ways of converting string to int.
parseInt(str,10)
parseFloat(str)
str << 0
+str
str*1
str-0
Number(str)
http://jsben.ch/#/zGJHM
http://phrogz.net/js/string_to_number.html
parseInt() -> Parses a number to specified redix.
Number()-> Converts the specified value to its numeric equivalent or NaN if it fails to do so.
Hence for converting some non-numeric value to number we should always use Number() function.
eg.
Number("")//0
parseInt("")//NaN
Number("123")//123
parseInt("123")//123
Number("123ac") //NaN,as it is a non numeric string
parsInt("123ac") //123,it parse decimal number outof string
Number(true)//1
parseInt(true) //NaN
There are various corner case to parseInt() functions as it does redix conversion, hence we should avoid using parseInt() function for coersion purposes.
Now, to check weather the provided value is Numeric or not,we should use nativeisNaN() function
I always use parseInt, but beware of leading zeroes that will force it into octal mode.
It's a good idea to stay away from parseInt and use Number and Math.round unless you need hex or octal. Both can use strings. Why stay away from it?
parseInt(0.001, 10)
0
parseInt(-0.0000000001, 10)
-1
parseInt(0.0000000001, 10)
1
parseInt(4000000000000000000000, 10)
4
It completely butchers really large or really small numbers. Oddly enough it works normally if these inputs are a string.
parseInt("-0.0000000001", 10)
0
parseInt("0.0000000001", 10)
0
parseInt("4000000000000000000000", 10)
4e+21
Instead of risking hard to find bugs with this and the other gotchas people mentioned, I would just avoid parseInt unless you need to parse something other than base 10. Number, Math.round, Math.floor, and .toFixed(0) can all do the same things parseInt can be used for without having these types of bugs.
If you really want or need to use parseInt for some of it's other qualities, never use it to convert floats to ints.
parseInt converts to a integer number, that is, it strips decimals. Number does not convert to integer.
Another way to get the result is to use the ~ operator
For most circumstances
~~someThing === parseInt(something)
but ~~ will return zero for strings that parseInt will accept with trailing other characters or with the number base spec (eg hex) and will also return zero when parseInt returns NaN. Another difference is that ~~ if given a bigint returns a bigint to which you can add another bigint whereas parseInt returns an ordinary floating point number (yes really - it gives exactly the same value as parseFloat) if the bigint is large
However for most circumstances ~~ is 30% faster than parseInt. It is only slower by 10% when something is a floating point represented as a string.
So if the more restricted scope of ~~ fits your need then save the computer time and give yourself less to type

Unexpected results in JavaScript

Using the node.js console, I get the following unexpected results:
> 2 + "3"
"23"
> 2 * "3"
6
Why does the first example favor string concatenation and integer multiplication in the second example? I would not expect concatenation between different types, but rather an error to be thrown. If this is the behavior in JS, how can I predict the type of the final result?
In JavaScript the + operator serves as both addition and concatenation (joining two strings together) and will default to concatenation when one of the two values is a string.
Since you are using it between an integer and a string it will default to concatentation. If you ever need to force the addition operation you will need to make sure all of your values are numbers. You can do this with parseInt() and parseFloat() functions.
2 + parseInt("3"); // 5
The * operator is for multiplication only and as such it will automatically cast strings to numbers to perform the operation.
Given the above there's another trick you can use to force string numbers to actually become numbers which is multiplying them by 1 *1.
2 + "3"*1; // 5
According to ECMAScript 2015 Language Specification (Addition operator, Multiplicative operators), the evaluation of additive expression is (lprim is the left primitive (lval converted to primitive), rprim is the right one):
...
If Type(lprim) is String or Type(rprim) is String, then
Let lstr be ToString(lprim).
ReturnIfAbrupt(lstr).
Let rstr be ToString(rprim).
ReturnIfAbrupt(rstr).
Return the String that is the result of concatenating lstr and rstr.
Let lnum be ToNumber(lprim).
ReturnIfAbrupt(lnum).
Let rnum be ToNumber(rprim).
ReturnIfAbrupt(rnum).
Return the result of applying the addition operation to lnum and rnum.
The evaluation of multiplicative expression is:
...
Let lnum be ToNumber(leftValue).
ReturnIfAbrupt(lnum).
Let rnum be ToNumber(rightValue).
ReturnIfAbrupt(rnum).
Return the result of applying the MultiplicativeOperator
You can see that if it is an additive expression, it is first to check whether there is a String. If there is a String, string concatenation is executed. Otherwise, the values are converted to Number and an addition operation is executed.
If it is a multiplicative expression, it would always convert values to Number and deliver a multiplicative operation.

Passing a number to parseFloat() instead of string

In my code, the value of a particular var can originate from any one of a number of different json sources. For some of those sources, the json element concerned will be a string (e.g. "temp": "10.2"), while for other sources the json element will already be a float (e.g. "temp": 10.2).
Does it do any harm (is anything likely to break) if I just pass the json element (from whatever source) through a parseFloat(), even if it's already a float? It seems to work; I'm just thinking about good/bad practice and possible breakage in future or on a different platform.
Thanks.
You should be able to call parseFloat() on a float or a string without any problems. If it is a float already, it's converted to a string first, and then to a float again, so it's a little less efficient, but it shouldn't matter too much.
You should still check the result for NaN, in case there's something unexpected in the data.
The most appropriate method to convert any datatype to a number is to use the Number function:
In a non-constructor context (i.e., without the new operator),
Number can be used to perform a type conversion.
Number("1234") // 1234
Number(1234) // 1234
This method differs from parseFloat in these ways at least:
Number function does not perform "double-conversion" if the input is already a number (ref)
Parse float converts the input to a string then extracts the number (ref)
Number function returns common sense values for most datatypes e.g. Number(true) yields 1
Parse float uses the string value of input so parseFloat(true) tries to parse number from "true" and yields NaN
Number function fails when input string is an invalid number e.g. Number("123abc") yields NaN
Parse float tries to parse as much of a number as possible e.g. parseFloat("123abc") yields 123
If you are sure the value is always a valid number, you should use Number(stringOrNumber).
If you need some additional safety using parseFloat() you could also write your own function which is also performance optimized:
function toFloat(value) {
return typeof value === 'number' ? value : parseFloat(value);
}
I also created a jsPerf test case that shows the performance is >30% better than the plain parseFloat() for a 1:1 ratio between strings and numbers as input values.
Nope there is no problem with passing a number to it
MDN says as long as it can be converted to a number, nothing breaking should happen.
If the first character cannot be converted to a number, parseFloat returns NaN.
As an alternative, you could use the unary operator + which does basically the same thing as parseFloat and also returns NaN if it didn't work.
For instance:
var myFloat = +('10.5');
var myOtherFloat = parseFloat('10.5', 10);
var alreadyAFloat = parseFloat(10.5, 10);
console.log(myFloat === myOtherFloat && myOtherFloat === alreadyAFloat); // true
Wether it's a float or a String using parseFloat() is much safer to avoid all kind of errors.
As you said it will always work, but if you enforce it to be a float you will avoid getting any Exception.
For Example:
Both parseFloat('10.2', 10) and parseFloat(10.2, 10) will work
perfectly and will give you the same result which is 10.2.
Personally I can't see this being a problem what so ever, to be honest I would always use the parsefloat() for one reason, and that is safety. You can never be to sure what may happen, so always predict the worse :D

Why does string to number comparison work in Javascript

I am trying to compare a value coming from a HTML text field with integers. And it works as expected.
Condition is -
x >= 1 && x <= 999;
Where x is the value of text field. Condition returns true whenever value is between 1-999 (inclusive), else false.
Problem is, that the value coming from the text field is of string type and I'm comparing it with integer types. Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
Because JavaScript defines >= and <= (and several other operators) in a way that allows them to coerce their operands to different types. It's just part of the definition of the operator.
In the case of <, >, <=, and >=, the gory details are laid out in ยง11.8.5 of the specification. The short version is: If both operands are strings (after having been coerced from objects, if necessary), it does a string comparison. Otherwise, it coerces the operands to numbers and does a numeric comparison.
Consequently, you get fun results, like that "90" > "100" (both are strings, it's a string comparison) but "90" < 100 (one of them is a number, it's a numeric comparison). :-)
Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
That's a matter of opinion. Some people think it's totally fine to rely on the implicit coercion; others think it isn't. There are some objective arguments. For instance, suppose you relied on implicit conversion and it was fine because you had those numeric constants, but later you were comparing x to another value you got from an input field. Now you're comparing strings, but the code looks the same. But again, it's a matter of opinion and you should make your own choice.
If you do decide to explicitly convert to numbers first, parseInt may or may not be what you want, and it doesn't do the same thing as the implicit conversion. Here's a rundown of options:
parseInt(str[, radix]) - Converts as much of the beginning of the string as it can into a whole (integer) number, ignoring extra characters at the end. So parseInt("10x") is 10; the x is ignored. Supports an optional radix (number base) argument, so parseInt("15", 16) is 21 (15 in hex). If there's no radix, assumes decimal unless the string starts with 0x (or 0X), in which case it skips those and assumes hex. Does not look for the new 0b (binary) or 0o (new style octal) prefixes; both of those parse as 0. (Some browsers used to treat strings starting with 0 as octal; that behavior was never specified, and was [specifically disallowed][2] in the ES5 specification.) Returns NaN if no parseable digits are found.
Number.parseInt(str[, radix]) - Exactly the same function as parseInt above. (Literally, Number.parseInt === parseInt is true.)
parseFloat(str) - Like parseInt, but does floating-point numbers and only supports decimal. Again extra characters on the string are ignored, so parseFloat("10.5x") is 10.5 (the x is ignored). As only decimal is supported, parseFloat("0x15") is 0 (because parsing ends at the x). Returns NaN if no parseable digits are found.
Number.parseFloat(str) - Exactly the same function as parseFloat above.
Unary +, e.g. +str - (E.g., implicit conversion) Converts the entire string to a number using floating point and JavaScript's standard number notation (just digits and a decimal point = decimal; 0x prefix = hex; 0b = binary [ES2015+]; 0o prefix = octal [ES2015+]; some implementations extend it to treat a leading 0 as octal, but not in strict mode). +"10x" is NaN because the x is not ignored. +"10" is 10, +"10.5" is 10.5, +"0x15" is 21, +"0o10" is 8 [ES2015+], +"0b101" is 5 [ES2015+]. Has a gotcha: +"" is 0, not NaN as you might expect.
Number(str) - Exactly like implicit conversion (e.g., like the unary + above), but slower on some implementations. (Not that it's likely to matter.)
Bitwise OR with zero, e.g. str|0 - Implicit conversion, like +str, but then it also converts the number to a 32-bit integer (and converts NaN to 0 if the string cannot be converted to a valid number).
So if it's okay that extra bits on the string are ignored, parseInt or parseFloat are fine. parseInt is quite handy for specifying radix. Unary + is useful for ensuring the entire string is considered. Takes your choice. :-)
For what it's worth, I tend to use this function:
const parseNumber = (str) => str ? +str : NaN;
(Or a variant that trims whitespace.) Note how it handles the issue with +"" being 0.
And finally: If you're converting to number and want to know whether the result is NaN, you might be tempted to do if (convertedValue === NaN). But that won't work, because as Rick points out below, comparisons involving NaN are always false. Instead, it's if (isNaN(convertedValue)).
The MDN's docs on Comparision states that the operands are converted to a common type before comparing (with the operator you're using):
The more commonly used abstract comparison (e.g. ==) converts the operands to the same Type before making the comparison. For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.
You'd only need to apply parseInt() if you were using a strict comparision, that does not perform the auto casting before comparing.
You should use parseInt if the var is a string. Add = to compare datatype value:
parseInt(x) >== 1 && parseInt(x) <== 999;

JavaScript Adding Booleans

console.log(true+true); //2
console.log(typeof(true+true)); //number
console.log(isNaN(true+true)); //false
Why is adding together 2 boolean types yielding a number? I kind of understand that if they didn't equal (1/0 (binary?)) it would be awkward to try to perform arithmetic on a boolean type, but I can't find the reasoning behind this logic.
It works like that because that's how it's specified to work.
EcmaScript standard specifies that unless either of the arguments is a string, the + operator is assumed to mean numeric addition and not string concatenation. Conversion to numeric values is explicitly mentioned:
Return the result of applying the addition operation to ToNumber( lprim) and ToNumber(rprim).
(where lprim and rprim are the primitive forms of the left-hand and the right-hand argument, respectively)
EcmaScript also specifies the To Number conversion for booleans clearly:
The result is 1 if the argument is true. The result is +0 if the argument is false.
Hence, true + true effectively means 1 + 1, or 2.
Javascript is loosely typed, and it automatically converts things into other things to fit the situation. That's why you can do var x without defining it as an int or bool
http://msdn.microsoft.com/en-us/library/6974wx4d(v=vs.94).aspx
Javascript is a dynamically typed language, because you don't have to specify what type something is when you start, like bool x or int i. When it sees an operation that can't really be done, it will convert the operands to whatever they need to be so that they can have that operation done on them. This is known as type coercion. You can't add booleans, so Javascript will cast the booleans to something that it can add, something like a string or a number. In this case, it makes sense to cast it to a number since 1 is often used to represent true and 0 for false. So Javascript will cast the true's to 1s, and add them together

Categories

Resources