代码之家  ›  专栏  ›  技术社区  ›  Å ime Vidas Zim84

将<input>值读取为数字而不是字符串(JavaScript)

  •  0
  • Å ime Vidas Zim84  · 技术社区  · 14 年前

    假设页面上有一个文本框:

    <input type="text">  
    

    访问者输入一些字符,我们通过 value 文本框的属性。

    现在,假设文本框代表一个数值。我不能在文本框中定义这样的东西-它的值总是一个字符串值。我可以做的是,将该sting值转换为数值:

    Number(input.value)
    

    但是,输入值被视为 字符串数字文本 ,而不是 数字文字 . 这意味着允许这些输入值(尽管它们不是JavaScript中的数字文本):

    • 带前导零的值(如“000003”)
    • “无限”值
    • 带加号的值(如“+3”)

    现在,让我们说-为了这个参数-我真的想把输入值读为 数字文字 . 我不想要带前导零或+号的数字,等等。我在想我怎样才能做到这一点,这就是我想到的:

    try  {                  
        var n = JSON.parse('{ "n": ' + this.value + ' }').n;
        if (typeof n !== "number") {
            throw "error";
        }
        // n is a Number value that represents the value of the text-box        
    } catch(e) {}
    

    这是代码的简化版本,此处提供了一个实时演示:
    http://vidasp.net/tinydemos/input-as-number.html

    注意:我使用try catch是因为如果输入值不是有效的JSON值,JSON.parse调用将失败(抛出错误)。

    你觉得这个方法怎么样。它有缺点吗?

    (一个缺点是无法读取十六进制数值,因为JSON不允许它们。)

    我刚刚意识到。。。

    ... 我之所以这么做,是因为我并没有把输入作为一个数字来读。我想要的是检查该值是否符合NumericLiteral语法-regexp检查很容易做到这一点。

    1 回复  |  直到 14 年前
        1
  •  4
  •   Christian C. Salvadó    14 年前

    JSON.parse 你将作为一个 JSONNumber 代币,不是真的 NumericLiteral .

    两者之间有区别 J序号 数字文字 , J序号 不允许前导零(无八进制)、十六进制文字或前导点( 3. )或相反,一个点后跟小数位数( .3 ),而且 JSON.parse解析 在SpiderMonkey(和json2.js库)中,对于数值,在实现中确实存在错误 JSON.parse('01') 不会像人们所期望的那样投掷。

    您可以进行验证以确保字符串符合 数字文字 语法,如果是的话,你可以使用 eval 或者 Function 构造函数来真正转换值,例如:

    var numericLiteral = (function () {
      var numericLiteralSyntax = new RegExp([
        '^0x[\\da-fA-F]+$', // HexIntegerLiteral
        '^0[0-7]+$',        // OctalIntegerLiteral
        '^(?:\\.\\d+|(?:0|[1-9]\\d*)(?:\\.\\d*)?)(?:[eE][+-]?\\d+)?$'//DecimalLiteral
      ].join('|'));
    
      return function (value) {
        if (typeof value != 'string') { throw TypeError('value must be a String'); }
    
        if (numericLiteralSyntax.test(value)) {
          return Function('return ' + value)(); // a NumericLiteral, evaluate it
        }
        throw SyntaxError('Invalid NumericLiteral'); // Not a NumericLiteral
      }
    })();
    
    numericLiteral('0xFF'); // 255, an HexIntegerLiteral
    numericLiteral('2e1'); // 20, DecimalLiteral with ExponentPart
    numericLiteral('3.'); // 3
    numericLiteral('.3'); // 0.3
    numericLiteral('3.1416'); // 3.1416
    numericLiteral('00010'); // 8, an OctalIntegerLiteral
    

    用于验证的regexp来自 SourceText JavaScript实用程序 Asen Bozhilov .