14

Firstly - my description ;)

I've got a XmlHttpRequests JSON response from the server. MySQL driver outputs all data as string and PHP returns it as it is, so any integer is returned as string, therefore:

Is there any fast alternative (hack) for parseInt() function in JS which can parse pure numeric string, e.g.

var foo = {"bar": "123"};
...
foo.bar = parseInt(foo.bar); // (int) 123
shfx
  • 1,261
  • 1
  • 11
  • 16
  • 1
    what about int=string*1? – dusoft Feb 27 '09 at 13:34
  • No need to multiply. Use unary operator: int = +string; (However every number in javascript is still a float (but I think I heard that V8 might have some optimizations and actually use ints) – some Feb 27 '09 at 16:35
  • 2
    I've created a nice little benchmark here :) http://jsperf.com/converting-string-to-int The results don't seem to be conclusive on the Mac I tested on, all ranging from very slow to super fast, depending on which browser. Ack! – Dominic K Aug 09 '11 at 23:46
  • `~~` will give you an integer; https://stackoverflow.com/questions/10841204/vs-parseint?noredirect=1&lq=1 – Miroslav Glamuzina Mar 12 '19 at 00:32

11 Answers11

47

To convert to an integer simply use the unary + operator, it should be the fastest way:

var int = +string;

Conversions to other types can be done in a similar manner:

var string = otherType + "";
var bool = !!anything;

More info.

Aistina
  • 12,435
  • 13
  • 69
  • 89
  • 1
    In Chrome, parseInt() is fastest: http://cl.ly/image/442b10002i3T If you account for the fact that you need to check for isNaN with parseInt and the unary operator, the double tilde is faster than unary, but parseInt still wins in Chrome. In IE, double tilde wins. See: http://jsperf.com/double-tilde-vs-parseint/6 – James Hartig Oct 09 '12 at 03:34
  • 5
    This is does not parse to int, it parses as number. e.g. +"1.5" === 1.5 – Jethro Larson Nov 12 '14 at 23:09
  • 4
    this answer is old, and incorrect, this does not convert to integer – Ayyash Sep 06 '18 at 04:59
  • `parseInt` removes trailing characters, while +string returns NaN. For ex: '123a' – Laxmikant Dange Oct 05 '21 at 08:46
20

Type casting in JavaScript is done via the constructor functions of the built-in types without new, ie

foo.bar = Number(foo.bar);

This differs from parseInt() in several ways:

  • leading zeros won't trigger octal mode
  • floating point values will be parsed as well
  • the whole string is parsed, i.e. if it contains additional non-numeric characters, the return value will be NaN
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Christoph
  • 164,997
  • 36
  • 182
  • 240
8

First off, have you actually documented that it's slow and is causing problems? Otherwise, I wouldn't bother looking for a solution, because there really isn't a problem.

Secondly, I would guess that since parseInt is a native JS-method, it would be implemented in a way that is very fast, and probably in the native language of the VM (probably C, depending on the browser/VM). I think you could have some trouble making a faster method out of pure JS. =)

Of course, I'm not a JS guru, so I don't know for sure, but this is what my intuition tells me, and tends to be the standard answer to "how would I make a faster alternative for libraryFunction()?" questions.

Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
Daniel Bruce
  • 11,269
  • 4
  • 30
  • 28
6

Cast it to an int in PHP before you json_encode() it:

$foo->bar = (int)$foo->bar;
print('var foo = ' . json_encode($foo));

Incidentally, when using parseInt it's good practice to always specify the second parameter unless you really want string starting with 0 to be interpreted as octal and so on:

parseInt('010', 10); // 10
Greg
  • 316,276
  • 54
  • 369
  • 333
3

Fast shortcut to parseInt is

("78.5" | 0) //bitwise or forces the string to parse as int

This is what ASM uses to represent ints in js.

Jethro Larson
  • 2,337
  • 1
  • 24
  • 24
3

The Number constructor also exists, but it should be the same as parseInt in term of speed (as already said you should correct the PHP part instead of the javascript one anyway) :

var i = "123";
i = new Number(i); // Number numeric wrapper
var j = "123";
j = Number(j); // Number primitive

BTW if someone is interested i searched by curiosity for the V8 (Google chrome) implementation of parseInt and it's here on google code.

Julien Roncaglia
  • 17,397
  • 4
  • 57
  • 75
2

You aren't going to get better than parseInt, but the real bug is that the PHP is providing what is supposed to be a number as a string.

And ditto to what Daniel said - don't go looking for micro-optimisations like this until you have benchmarked your code and discovered that it's worth doing.

1

How slow can it be? How many times per second is this process being called? How many different numeric return values are there? I whipped together a script and tested 100,000 numbers. Parsing them from strings took 687ms. Searching them in an array took 541ms. That's a very small improvement. I agree with other posters. You may not get better than the native parseInt() method.

souLTower
  • 656
  • 1
  • 5
  • 5
1

Casting is a wee bit faster than parsing but slower than searching.

Also, in Firefox the fastest method turns out to be parseInt() followed by searching. Firefox also turned out to be 6 times faster on average than IE. Interesting.

Cool idea using the unary operator. In Firefox that turned out to be comparable to parseInt(). In IE it turned out to be the fastest method.

souLTower
  • 656
  • 1
  • 5
  • 5
0

This solution is faster than parseInt() if you parse strings of decimal integer that is 20 or less in length. For some browser, you may still be faster than parseInt() up to 33 digits in length. Also, you still be faster than auto-cast.

It is because, the parseInt() for the browser does take some time to warm up, so if you only using a simple method to parse, you beat it for a while until it catches up. Don't use this for nodeJS though. When run parseInt() from nodeJS, it is startup time is a lot less than when running from a browser.

45 is the '-' sign in ASCII, 43 is the '+' sign in ASCII. 48 is '0'. Only 48 to 57 xor 48 become 0 - 9(in their order). No other numbers xor 48 yields 0-9.

This will return undefined if the string is not a valid decimal integer string or if the string is empty. It throws a string with value "Not a string" if the input is not of type string.

var toNumber = function (input) {
    if ( typeof input !== "string" ) throw "Not a string";

    var length = input.length;
    if ( length === 0 ) return;
    var c1 = input.charCodeAt(0); 

    if ( c1 === 45 || c1 === 43 ){
        if ( length === 1 ) return;
        var start = 1;
    } else {
        var start = 0;
    }

    var out = 0, c;    
    while( start < length && input.charCodeAt(start) === 48 ) start++;

    for ( ; start < length; start++){
        c = input.charCodeAt(start) ^ 48;
        if ( c > 9 ) return;
        out = (out * 10) + c;
    }

    if ( c1 === 45 ) return out * -1;
    return out;
}
Kevin Ng
  • 2,146
  • 1
  • 13
  • 18
0

if the objects are larger you could try JSON, it is a typed format so you do not need to convert the values.

TheHippo
  • 61,720
  • 15
  • 75
  • 100