---
type: how-to
language: javascript
slug: string/to-number
title: "文字列を数値に変換する"
title_tag: "JavaScript 文字列を数値に変換 — Number と parseInt の違い"
summary: >
  Number() と parseInt() と単項プラスは、失敗したときの振る舞いが違います。
  空文字・全角・単位つき・カンマ区切りで何が起きるかを実行して確かめ、安全な書き方をまとめます。
description: >
  Number() と parseInt() は失敗の仕方が違います。空文字が0になる、途中まで読む、全角数字が通らない。失敗を確実に見分ける書き方まで実行して確かめられます。
status: published
difficulty: 2
minutes: 9

versions:
  verified: "Node 22.22.3"
  since: "ES1"
  deprecated: null
  removed: null

sources:
  - title: "Number ( value ) — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-number-constructor-number-value"
  - title: "parseInt ( string, radix ) — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-parseint-string-radix"
  - title: "Number() コンストラクター — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/Number"

terms: [型変換, NaN, 基数]

links:
  related:
    - javascript/why/nan-equality
    - javascript/why/float-precision
    - javascript/reference/string/split
    - javascript/how-to/string/format-date
    - javascript/why/strict-equality
    - javascript/errors/invalid-array-length

content_updated_at: 2026-09-07
published_at: 2026-09-07
---

## 答え

`Number()` を使い、**空文字を先に弾き、変換できたかを確かめます。**

```js run
function toNumber(text) {
  const s = String(text).trim();
  if (s === '') return null;

  const n = Number(s);
  return Number.isFinite(n) ? n : null;
}

console.log(toNumber('42'));
console.log(toNumber('3.14'));
console.log(toNumber('42px'));
console.log(toNumber(''));
```
```output
42
3.14
null
null
```

関門は[num:2]つあります。

- **空文字を先に弾く** … `Number('')` は `NaN` ではなく[bad:0]になる
- **`Number.isFinite()` で確かめる** … `NaN` も `Infinity` もまとめて落ちる

どちらも省くと静かに壊れます。理由はこのあと順に見ます。

上のコードは書き換えて実行できます。`'42px'` を `'  42  '` にしてみてください。

## 3つのやり方の違い

```js run
const inputs = ['42', '3.14', '42px', '', '  7 ', 'あ', '0x1f', '1e3'];

for (const s of inputs) {
  console.log(
    JSON.stringify(s).padEnd(8),
    'Number:', String(Number(s)).padEnd(6),
    'parseInt:', String(parseInt(s, 10)).padEnd(6),
    'parseFloat:', parseFloat(s),
  );
}
```
```output
"42"     Number: 42     parseInt: 42     parseFloat: 42
"3.14"   Number: 3.14   parseInt: 3      parseFloat: 3.14
"42px"   Number: NaN    parseInt: 42     parseFloat: 42
""       Number: 0      parseInt: NaN    parseFloat: NaN
"  7 "   Number: 7      parseInt: 7      parseFloat: 7
"あ"      Number: NaN    parseInt: NaN    parseFloat: NaN
"0x1f"   Number: 31     parseInt: 0      parseFloat: 0
"1e3"    Number: 1000   parseInt: 1      parseFloat: 1000
```

| | 全体が数値でないとき | 空文字 | 小数点 |
|---|---|---|---|
| `Number()` | [em:NaN]（厳しい） | [bad:0 になる] | 読む |
| `parseInt()` | [bad:読める所まで読む] | `NaN` | [bad:切り捨てる] |
| `parseFloat()` | [bad:読める所まで読む] | `NaN` | 読む |

**入力の検証には `Number()`** を使ってください。
`parseInt()` は `'42px'` を `42` として通してしまいます。

## 空文字が 0 になる

`Number()` のいちばんの落とし穴です。**未入力が `0` として通ります。**

```js bad
console.log(Number(''));
console.log(Number('   '));
console.log(Number(null));
console.log(Number([]));
console.log(Number(false));
```
```output
0
0
0
0
0
```

フォームの未入力は空文字で届きます。そのまま `Number()` に渡すと
[bad:「0 と入力された」と区別できません]。

```js run
const guarded = (text) => (text.trim() === '' ? null : Number(text));

console.log(guarded(''));
console.log(guarded('   '));
console.log(guarded('0'));
```
```output
null
null
0
```

**先に空かどうかを見れば、「未入力」と「0 と入力」を区別できます。**

## 単項プラスは Number() と同じ

`+text` は短く書けますが、中身は `Number()` です。空文字も `0` になります。

```js run
console.log(+'42', Number('42'));
console.log(+'', Number(''));
console.log(+'42px', Number('42px'));
```
```output
42 42
0 0
NaN NaN
```

[dim:短いぶん、変換していることが読み取りにくくなります。人が読むコードでは Number() を勧めます。]

## parseInt には必ず基数を渡す

第2引数を省くと、[num:2]文字目までを見て[type:基数]を決めます。

```js run
console.log(parseInt('0x1f'));
console.log(parseInt('0x1f', 10));
console.log(parseInt('08'));
console.log(parseInt('08', 10));
```
```output
31
0
8
8
```

`'0x1f'` は[num:16]進数とみなされて `31` になります。
`'08'` は現在の仕様では[num:10]進数ですが、**古い環境では[num:8]進数として `0` になりました。**

**`parseInt(s, 10)` と必ず書いてください。**

## カンマ区切りと全角

そのままでは通りません。**先に整えます。**

```js bad
console.log(Number('1,234'));
console.log(Number('１２３'));
console.log(Number('12３'));
```
```output
NaN
NaN
NaN
```

**全角数字は1文字でも混ざると変換できません。** カンマも同じです。

日本語の入力欄では[key:全角で打たれるのが普通]です。
「数字を入れてください」と書いても、全角で来ます。**受け取る側で直してください。**

```js run
function normalize(text) {
  return text
    .replace(/[０-９．－]/g, (c) => String.fromCharCode(c.charCodeAt(0) - 0xfee0))
    .replace(/,/g, '')
    .trim();
}

console.log(Number(normalize('1,234')));
console.log(Number(normalize('１２３')));
console.log(Number(normalize('12３')));
console.log(Number(normalize(' １，２３４ '.replace(/，/g, ','))));
```
```output
1234
123
123
1234
```

[dim:全角の記号は種類が多いので、扱う範囲を決めて明示的に置き換えてください。何でも受け付けようとすると、かえって読めなくなります。]

区切って複数の数値を受け取るなら
[String.prototype.split()](/ja/javascript/reference/string/split/) と組み合わせます。

## 大きすぎる数

[num:16]桁を超えると、変換できても[bad:元に戻りません]。

```js bad
const text = '9007199254740993';

console.log(Number(text));
console.log(String(Number(text)) === text);
```
```output
9007199254740992
false
```

ID や電話番号のような「計算しない数字」は、**数値に変換しないでください。**
文字列のまま扱うのが正解です。

計算が必要なら `BigInt` を使います。

```js run
const text = '9007199254740993';

console.log(BigInt(text));
console.log(String(BigInt(text)) === text);
```
```output
9007199254740993n
true
```

理由は
[なぜ 0.1 + 0.2 は 0.30000000000000004 になるのか](/ja/javascript/why/float-precision/) にあります。

## NaN の判定に isNaN() を使わない

グローバルの `isNaN()` は[bad:先に数値へ変換します]。別の質問に答えてしまいます。

```js bad
console.log(isNaN('あ'));
console.log(isNaN(''));
console.log(Number.isNaN(Number('')));
```
```output
true
false
false
```

`Number.isNaN()` か `Number.isFinite()` を使ってください。
詳しくは
[なぜ NaN === NaN は false なのか](/ja/javascript/why/nan-equality/) にあります。

## まとめ

```js run
function toNumber(text) {
  if (typeof text !== 'string') return null;

  const s = text.trim();
  if (s === '') return null;

  const n = Number(s);
  return Number.isFinite(n) ? n : null;
}

for (const s of ['42', '3.14', '', '  ', '42px', 'あ', '1e3', 'Infinity']) {
  console.log(JSON.stringify(s).padEnd(10), toNumber(s));
}
```
```output
"42"       42
"3.14"     3.14
""         null
"  "       null
"42px"     null
"あ"        null
"1e3"      1000
"Infinity" null
```

- 変換には **`Number()`**（`parseInt()` は途中まで読んでしまう）
- **空文字を先に弾く**（`Number('')` は `0`）
- **`Number.isFinite()` で確かめる**（`NaN` も `Infinity` も落ちる）
- `parseInt()` を使うときは[key:必ず基数を渡す]
- 計算しない数字（ID・電話番号）は[bad:変換しない]
