(Built-in) way in JavaScript to check if a string is a valid number

前端 未结 30 3384
-上瘾入骨i
-上瘾入骨i 2020-11-22 01:54

I\'m hoping there\'s something in the same conceptual space as the old VB6 IsNumeric() function?

相关标签:
30条回答
  • 2020-11-22 02:22
    function isNumberCandidate(s) {
      const str = (''+ s).trim();
      if (str.length === 0) return false;
      return !isNaN(+str);
    }
    
    console.log(isNumberCandidate('1'));       // true
    console.log(isNumberCandidate('a'));       // false
    console.log(isNumberCandidate('000'));     // true
    console.log(isNumberCandidate('1a'));      // false 
    console.log(isNumberCandidate('1e'));      // false
    console.log(isNumberCandidate('1e-1'));    // true
    console.log(isNumberCandidate('123.3'));   // true
    console.log(isNumberCandidate(''));        // false
    console.log(isNumberCandidate(' '));       // false
    console.log(isNumberCandidate(1));         // true
    console.log(isNumberCandidate(0));         // true
    console.log(isNumberCandidate(NaN));       // false
    console.log(isNumberCandidate(undefined)); // false
    console.log(isNumberCandidate(null));      // false
    console.log(isNumberCandidate(-1));        // true
    console.log(isNumberCandidate('-1'));      // true
    console.log(isNumberCandidate('-1.2'));    // true
    console.log(isNumberCandidate(0.0000001)); // true
    console.log(isNumberCandidate('0.0000001')); // true
    console.log(isNumberCandidate(Infinity));    // true
    console.log(isNumberCandidate(-Infinity));    // true
    
    console.log(isNumberCandidate('Infinity'));  // true
    
    if (isNumberCandidate(s)) {
      // use +s as a number
      +s ...
    }
    
    0 讨论(0)
  • 2020-11-22 02:22

    Save yourself the headache of trying to find a "built-in" solution.

    There isn't a good answer, and the hugely upvoted answer in this thread is wrong.

    npm install is-number

    In JavaScript, it's not always as straightforward as it should be to reliably check if a value is a number. It's common for devs to use +, -, or Number() to cast a string value to a number (for example, when values are returned from user input, regex matches, parsers, etc). But there are many non-intuitive edge cases that yield unexpected results:

    console.log(+[]); //=> 0
    console.log(+''); //=> 0
    console.log(+'   '); //=> 0
    console.log(typeof NaN); //=> 'number'
    
    0 讨论(0)
  • 2020-11-22 02:24

    2019: Including ES3, ES6 and TypeScript Examples

    Maybe this has been rehashed too many times, however I fought with this one today too and wanted to post my answer, as I didn't see any other answer that does it as simply or thoroughly:

    ES3

    var isNumeric = function(num){
        return (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);  
    }
    

    ES6

    const isNumeric = (num) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);
    

    Typescript

    const isNumeric = (num: any) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num as number);
    

    This seems quite simple and covers all the bases I saw on the many other posts and thought up myself:

    // Positive Cases
    console.log(0, isNumeric(0) === true);
    console.log(1, isNumeric(1) === true);
    console.log(1234567890, isNumeric(1234567890) === true);
    console.log('1234567890', isNumeric('1234567890') === true);
    console.log('0', isNumeric('0') === true);
    console.log('1', isNumeric('1') === true);
    console.log('1.1', isNumeric('1.1') === true);
    console.log('-1', isNumeric('-1') === true);
    console.log('-1.2354', isNumeric('-1.2354') === true);
    console.log('-1234567890', isNumeric('-1234567890') === true);
    console.log(-1, isNumeric(-1) === true);
    console.log(-32.1, isNumeric(-32.1) === true);
    console.log('0x1', isNumeric('0x1') === true);  // Valid number in hex
    // Negative Cases
    console.log(true, isNumeric(true) === false);
    console.log(false, isNumeric(false) === false);
    console.log('1..1', isNumeric('1..1') === false);
    console.log('1,1', isNumeric('1,1') === false);
    console.log('-32.1.12', isNumeric('-32.1.12') === false);
    console.log('[blank]', isNumeric('') === false);
    console.log('[spaces]', isNumeric('   ') === false);
    console.log('null', isNumeric(null) === false);
    console.log('undefined', isNumeric(undefined) === false);
    console.log([], isNumeric([]) === false);
    console.log('NaN', isNumeric(NaN) === false);
    

    You can also try your own isNumeric function and just past in these use cases and scan for "true" for all of them.

    Or, to see the values that each return:

    0 讨论(0)
  • 2020-11-22 02:25

    My solution:

    // returns true for positive ints; 
    // no scientific notation, hexadecimals or floating point dots
    
    var isPositiveInt = function(str) { 
       var result = true, chr;
       for (var i = 0, n = str.length; i < n; i++) {
           chr = str.charAt(i);
           if ((chr < "0" || chr > "9") && chr != ",") { //not digit or thousands separator
             result = false;
             break;
           };
           if (i == 0 && (chr == "0" || chr == ",")) {  //should not start with 0 or ,
             result = false;
             break;
           };
       };
       return result;
     };
    

    You can add additional conditions inside the loop, to fit you particular needs.

    0 讨论(0)
  • 2020-11-22 02:25

    You could make use of types, like with the flow library, to get static, compile time checking. Of course not terribly useful for user input.

    // @flow
    
    function acceptsNumber(value: number) {
      // ...
    }
    
    acceptsNumber(42);       // Works!
    acceptsNumber(3.14);     // Works!
    acceptsNumber(NaN);      // Works!
    acceptsNumber(Infinity); // Works!
    acceptsNumber("foo");    // Error!
    
    0 讨论(0)
  • 2020-11-22 02:26

    2nd October 2020: note that many bare-bones approaches are fraught with subtle bugs (eg. whitespace, implicit partial parsing, radix, coercion of arrays etc.) that many of the answers here fail to take into account. The following implementation might work for you, but note that it does not cater for number separators other than the decimal point ".":

    function isNumeric(str) {
      if (typeof str != "string") return false // we only process strings!  
      return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
             !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
    }
    

    To check if a variable (including a string) is a number, check if it is not a number:

    This works regardless of whether the variable content is a string or number.

    isNaN(num)         // returns true if the variable does NOT contain a valid number
    

    Examples

    isNaN(123)         // false
    isNaN('123')       // false
    isNaN('1e10000')   // false (This translates to Infinity, which is a number)
    isNaN('foo')       // true
    isNaN('10px')      // true
    

    Of course, you can negate this if you need to. For example, to implement the IsNumeric example you gave:

    function isNumeric(num){
      return !isNaN(num)
    }
    

    To convert a string containing a number into a number:

    Only works if the string only contains numeric characters, else it returns NaN.

    +num               // returns the numeric value of the string, or NaN 
                       // if the string isn't purely numeric characters
    

    Examples

    +'12'              // 12
    +'12.'             // 12
    +'12..'            // NaN
    +'.12'             // 0.12
    +'..12'            // NaN
    +'foo'             // NaN
    +'12px'            // NaN
    

    To convert a string loosely to a number

    Useful for converting '12px' to 12, for example:

    parseInt(num)      // extracts a numeric value from the 
                       // start of the string, or NaN.
    

    Examples

    parseInt('12')     // 12
    parseInt('aaa')    // NaN
    parseInt('12px')   // 12
    parseInt('foo2')   // NaN      These last two may be different
    parseInt('12a5')   // 12       from what you expected to see. 
    

    Floats

    Bear in mind that, unlike +num, parseInt (as the name suggests) will convert a float into an integer by chopping off everything following the decimal point (if you want to use parseInt() because of this behaviour, you're probably better off using another method instead):

    +'12.345'          // 12.345
    parseInt(12.345)   // 12
    parseInt('12.345') // 12
    

    Empty strings

    Empty strings may be a little counter-intuitive. +num converts empty strings or strings with spaces to zero, and isNaN() assumes the same:

    +''                // 0
    +'   '             // 0
    isNaN('')          // false
    isNaN('   ')       // false
    

    But parseInt() does not agree:

    parseInt('')       // NaN
    parseInt('   ')    // NaN
    
    0 讨论(0)
提交回复
热议问题