Проверить, содержит ли переменная числовое значение в Javascript? - PullRequest
11 голосов
/ 02 марта 2009

В PHP это довольно просто:

is_numeric(23);//true
is_numeric("23");//true
is_numeric(23.5);//true
is_numeric(true);//false

Но как мне это сделать в Javascript? Я мог бы использовать регулярное выражение, но есть ли для этого функция?

Ответы [ 8 ]

24 голосов
/ 02 марта 2009

А как же:

function isNumber(n){
    return typeof(n) != "boolean" && !isNaN(n);
}

Встроенная функция isNaN используется для проверки, является ли значение не числом.

Обновление: Кристоф прав, в JavaScript логические типы конвертируются в Number, возвращая 1 для true и 0 для false, поэтому если вы оцениваете 1 + true, результат будет 2.

Учитывая это поведение, я обновил функцию, чтобы предотвратить преобразование логических значений в ее числовое представление.

14 голосов
/ 02 марта 2009

Я не думаю, что какие-либо предложения до сих пор действительно работают. Например,

!isNaN(parseFloat(foo))

нет, потому что parseFloat() игнорирует конечные нечисловые символы.

Чтобы обойти это, вы можете сравнить возвращаемое значение с значением, возвращаемым приведением через Number() (или эквивалентно, используя унарный +, но я предпочитаю явное приведение):

parseFloat(foo) === Number(foo)

Это все равно будет работать, если обе функции вернут NaN, поскольку NaN !== NaN равно true.

Другой возможностью было бы сначала привести к строке, затем к нумерации, а затем проверить на NaN, то есть

!isNaN(Number(String(foo)))

или эквивалентно, но менее читабельно (но, скорее всего, быстрее)

!isNaN(+('' + foo))

Если вы хотите исключить значения бесконечности, используйте isFinite() вместо !isNaN(), т.е.

isFinite(Number(String(foo)))

Явное приведение через Number() на самом деле не нужно, потому что isNan() и isFinite() приводят к числу неявно - вот почему !isNaN() не работает!

На мой взгляд, наиболее подходящим решением будет

isFinite(String(foo))

Как указал Мэтью, второй подход не обрабатывает строки, которые содержат только пробелы.

Исправить несложно - используйте код из комментария Мэтью или

isFinite(String(foo).trim() || NaN)

Вам придется решить, будет ли это лучше, чем сравнивать результаты parseFloat() и Number().

5 голосов
/ 02 марта 2009

Для проверки типов в JavaScript вы можете использовать оператор typeof:

js> var x = 1;
js> typeof(x);
number

Итак:

if (typeof(x) === 'number') {
   // Do something
}

Если вы хотите привести значение переменной к целому числу, вы можете использовать parseInt(x, 10), который будет анализировать значение как целое число в базе 10. Аналогично, вы можете использовать parseFloat, если вам нужно значение с плавающей запятой. , Однако они всегда приводятся независимо от типа, поэтому передача null, true и т. Д. Всегда будет возвращать число. Тем не менее, вы можете проверить, является ли это действительный номер, позвонив isNaN.

Итак, все вместе:

!isNaN(parseFloat(23)) // true
!isNaN(parseFloat('23')) // true
!isNaN(parseFloat(23.5)) // true
!isNaN(parseFloat(true)) // false

или

function isNumber(x) {
    return !isNaN(parseFloat(x));
}
3 голосов
/ 02 марта 2009

Проверяет числовые значения, включая отрицательные числа и числа с плавающей запятой.

function is_numeric(val){
    return val && /^-?\d+(\.\d+)?$/.test(val + '');
}

@ Vordreller: я исправил регулярное выражение. Теперь он должен работать правильно.

1 голос
/ 02 марта 2009
function is_numeric(val) {
  return ((+val) == val);
}

Это должно сработать.

0 голосов
/ 01 февраля 2018

Запустите фрагмент кода, чтобы увидеть сравнение лучших ответов по этой теме.

Некоторые контрольные примеры не выделены (и не способствуют обобщению). Эти случаи помечаются как неоднозначные, поскольку неясно, следует ли данное значение считать числом.

// Each of these functions should output a truthy/falsy value if the input is
// a number
const solutionsToTest = [
  v => parseFloat(v),
  v => Number(v),
  v => !isNaN(v),
  v => typeof v != "boolean" && !isNaN(v),
  v => isFinite(String(v)),
  v => !isNaN(parseFloat(v)) && isFinite(v)
];

const testCases = [
  //[ Test Name, Test Value, Expected Output, Is Ambiguous ]

  // Whitespace
  ['""', "", false, false],
  ['"\\t"', "\t", false, false],
  ['" "', " ", false, false],

  // Infinity
  ['"Infinity"', "Infinity", false, true],
  ['"+Infinity"', "Infinity", false, true],
  ["-Infinity", -Infinity, false, true],
  ["Infinity", Infinity, false, true],

  // Numbers mixed with symbols
  ['"123abc"', "123abc", false, true],
  ['"abc123"', "abc123", false, false],
  ['".0."', ".0.", false, false],
  ['"1."', "1.", true, true],
  ['"."', ".", false, true],
  ['"01"', "01", true, true],
  ['"-0"', "-0", true, true],
  ["+1", +1, true, true],
  ["-1", -1, true, true],

  // Other js types
  ["'null'", "null", false, false],
  ["'true'", "true", false, false],
  ["'false'", "false", false, false],
  ["null", null, false, false],
  ["true", true, false, false],
  ["false", false, false, false],
  ["NaN", NaN, false, false],
  ["[]", [], false, false],
  ["{}", {}, false, false],
  ["/./", /./, false, false],
  ["() => {}", () => {}, false, false]
];

const styles = {
  code: {
    fontFamily: "monospace",
    fontSize: 16
  },
  success: {
    backgroundColor: "#00ff5478"
  },
  failure: {
    backgroundColor: "#ff00008c"
  }
};

class TestCaseTable extends React.Component {
  static renderTableHeader(solutionsToTest) {
    return (
      <tr>
        <th>
          <p>Test Case</p>
        </th>
        {solutionsToTest.map(f => (
          <th key={f.toString()}>
            <p style={styles.code}>{f.toString()}</p>
          </th>
        ))}
      </tr>
    );
  }
  static renderTableRow(testCase, solutionsToTest) {
    const [testName, input, expectedOutput, isAmbiguous] = testCase;
    return (
      <tr key={testName}>
        <td style={styles.code}>{testName}</td>
        {solutionsToTest.map(f => {
          const output = Boolean(f(input));
          const style = isAmbiguous
            ? {}
            : output == expectedOutput ? styles.success : styles.failure;
          return (
            <td style={style} key={f.toString()}>
              <p>{output + ""}</p>
            </td>
          );
        })}
      </tr>
    );
  }
  render() {
    // Sort test cases, put the ambiguous ones after (but maintain stable sort
    // order)
    let sortedCases = [
      ...testCases.filter(([a, b, c, ambiguous]) => !ambiguous),
      ...testCases.filter(([a, b, c, ambiguous]) => ambiguous)
    ];
    return (
      <table>
        <thead>{TestCaseTable.renderTableHeader(solutionsToTest)}</thead>
        <tbody>
          {sortedCases.map(tc =>
            TestCaseTable.renderTableRow(tc, solutionsToTest)
          )}
        </tbody>
      </table>
    );
  }
}
class TestCaseSummaryTable extends React.Component {
  renderTableHeader(solutionsToTest) {
    return (
      <tr>
        <th>Summary</th>
        {solutionsToTest.map(f => (
          <th key={f.toString()}>
            <p style={styles.code}>{f.toString()}</p>
          </th>
        ))}
      </tr>
    );
  }
  renderSuccessRateRow(solutionsToTest, testCases) {
    // Ignore potentially ambiguous test cases
    testCases = testCases.filter(
      ([name, input, expected, ambiguous]) => !ambiguous
    );

    const numSuccess = testSolution =>
      testCases.reduce((succeeded, [name, input, expected]) => {
        return succeeded + (Boolean(testSolution(input)) == expected ? 1 : 0);
      }, 0);

    return (
      <tr>
        <td>
          <p>Test Success</p>
        </td>
        {solutionsToTest.map(f => (
          <td>
            <p>
              {numSuccess(f)} / {testCases.length}
            </p>
          </td>
        ))}
      </tr>
    );
  }
  render() {
    return (
      <table>
        <thead>{this.renderTableHeader(solutionsToTest)}</thead>
        <tbody>{this.renderSuccessRateRow(solutionsToTest, testCases)}</tbody>
      </table>
    );
  }
}

const root = () => {
  return (
    <div>
      <TestCaseSummaryTable />
      <TestCaseTable />
    </div>
  );
};

ReactDOM.render(root(), document.querySelector("#application"));
td {
  text-align: center;
  vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="application"></div>
0 голосов
/ 19 июля 2014

Вот некоторые тесты для isNaN против isFinite и typeof === "number"

http://jsperf.com/isnan-vs-isfinite-vs/3

Видимо typeof === "число" примерно в 5 раз быстрее

0 голосов
/ 15 декабря 2012

Вот что я придумал:

value = "2.34";
if (parseFloat(value).toString() === value) {
    alert("number");
}

Это должно работать с плавающими и целыми числами, положительными и отрицательными. Я не знаю о бесконечности, как обсуждали некоторые из ответов выше.

Если вашим значением может быть число, а не всегда строка, вы можете изменить === на ==, и оно будет обрабатывать оба.

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