Чтение <input>значений в виде чисел, а не строк (JavaScript) - PullRequest
0 голосов
/ 13 ноября 2010

Предположим, у нас есть текстовое поле на странице:

<input type="text">  

Посетитель вводит некоторые символы, и мы читаем эти символы через свойство value текстового поля.

Теперь предположим, что текстовое поле представляет собой числовое значение. Я не могу определить такую ​​вещь в текстовом поле - его значение всегда будет строковым значением. Что я могу сделать, так это преобразовать это значение в числовое значение:

Number(input.value)

Однако входное значение обрабатывается как StringNumericLiteral , а не NumericLiteral . Это означает, что эти входные значения разрешены (хотя они не являются числовыми литералами в JavaScript):

  • значения с ведущими нулями (например, "000003")
  • значение "Бесконечность"
  • значения со знаком плюс (например, "+3")

Теперь давайте скажем, что - ради аргумента - я действительно хочу прочитать входное значение как NumericLiteral . Мне не нужны числа с ведущими нулями или знаком + и т. Д. Я думал, как мне это сделать, и вот что я придумал:

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 - что легко может сделать проверка регулярного выражения.

1 Ответ

4 голосов
/ 13 ноября 2010

С JSON.parse вы будете обрабатывать свое значение как JSONNumber токен, а не как NumericLiteral.

Существуют различия между JSONNumber и NumericLiteral, JSONNumber не допускает ни начальных нулей (без восьмеричных чисел), ни шестнадцатеричных литералов, ни ведущей точки (3.), ни наоборот, за точкой следует цифрами дроби (.3), кроме того, JSON.parse действительно глючит во всех реализациях, относительно числовых значений, в SpiderMonkey (и в библиотеке json2.js) JSON.parse('01') не будет выдавать, как можно ожидать.

Вы можете выполнить проверку, чтобы убедиться, что строка соответствует грамматике NumericLiteral, и если это так, вы можете использовать либо конструктор 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

RegExps для проверки получены из SourceText Утилита JavaScript от Асен Божилов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...