3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScript: parseInt(n, 10)の振る舞いを40の具体例から確認してみた

Posted at

JavaScriptで、文字列を整数としてパースする方法としてparseInt(n, 10)があります。この投稿では、nにどんな値を与えたらどんな戻り値になるのかを具体例をもとに検証していきます。

parseIntの基本的なこと

parseIntは第1引数に文字列の値を取ることができ、それを整数値のnumber型に変換する関数です。第2引数は、基数を指定します。基数は省略可能で、省略した場合は第1引数がどんな文字列で始まるかで基数を仮定します。例えば、"0x"始まりなら16"0"始まりなら8といった具合にです。第2引数は極力指定するほうが良いとされています。parseIntで整数と解釈できなかった場合はNaNが戻り値になります。

parseIntの詳細については次のMDNのドキュメントをご覧ください。

parseIntの仕様書を確認したい方は、次のECMAScript 2022の仕様書をご覧ください。

parseInt(n, 10)に様々な文字列を与えてみる

ここからはparseInt(n, 10)に様々な文字列を与えてみて、どのような戻り値になるか見ていきます。

まず、テストを手軽に行いたいので、次のようなテスト実行関数を作っておきます。この関数testは、引数casesに文字列配列を与えると、入力とパース結果の表が出力されるようになっています。

function test(cases) {
  console.table(cases.map((value) => [value, parseInt(value, 10)]));
}

符号

まず、符号がどう扱われるか見てみます。

test(["-1", "-0", "0", "1", "+0", "+1"]);
入力 結果
'-1' -1
'-0' -0
'0' 0
'1' 1
'+0' 0
'+1' 1

1文字目が負の符号の場合は、負の整数としてパースされます。JavaScriptは0にも符号がつけられるので、"-0"-0になります。

小数

次に小数です。

test(["-1.2", "-0.1", "-0.0", "0.0", "0.1", "1.2", "+0.0", "+0.1", "+1.2"]);
入力 結果
'-1.2' -1
'-0.1' -0
'-0.0' -0
'0.0' 0
'0.1' 0
'1.2' 1
'+0.0' 0
'+0.1' 0
'+1.2' 1

小数風の文字列は.以降が無視されるような振る舞いです。

数字に続く数字以外の文字

test(["0px", "-0px", "1px", "-1px"]);
入力 結果
'0px' 0
'-0px' -0
'1px' 1
'-1px' -1

文字列が数字で始まっている場合、数字じゃない文字に出くわすまで整数としてパースされます。

桁区切り文字

ES2021からはnumeric separatorという文法が追加されて、numberリテラルに桁の区切りを書けるようになりました。桁の区切り文字は_です。例えば、10001_000は同じ値になります。parseIntではnumeric separator風の文字列を扱えるのか試します。

test(["123_456", "123,456"]);
入力 結果
'123_456' 123
'123,456' 123

これもやはり、数字以外の文字に出会うとそこでパースをやめます。

bigint風の文字列

ES2020からはbigint型が追加されました。bigintはリテラル表記で数字の末尾にnを書く形式です。例えば、100nはbigint型の100になります。parseIntではbigintリテラル風の文字列がどう扱われるのでしょうか。

test(["1n", "1000n"]);
入力 結果
'1n' 1
'1000n' 1000

末尾のnは単純に無視されます。

0始まりの数字

0で始まる数字を見ていきます。

test(["05", "005", "050", "00", "00500px"]);
入力 結果
'05' 5
'005' 5
'050' 50
'00' 0
'00500px' 500

文字列のはじめにある0は無視されます。

前後に空白文字がある数字

前後に空白文字が入っている数字はどうでしょうか。

test([" 1 ", "\n1\n", "\t1\t"]);
入力 結果
' 1 ' 1
'\n1\n' 1
'\t1\t' 1

数字の前後の空白は取り除かれた上でパースされます。

NaNになる文字列

最後に結果がNaN、つまりパース失敗になるケースを見ていきます。

test(["", "a", "-", "+", "a0", "a1", "a1b"]);
入力 結果
'' NaN
'a' NaN
'-' NaN
'+' NaN
'a0' NaN
'a1' NaN
'a1b' NaN

空白文字やそもそも数字を含んでいないのはNaNになります。数字を含んでいても、-+を以外の文字で始まる文字列はNaNになります。

確認した振る舞いのまとめ

parseInt(n, 10)

  • 正負の符号は解釈される
  • 前後の空白文字は取り除かれた上で、パースされる
  • 1文字目が数字じゃないとNaNになる
  • 1文字目が数字なら、途中に数字以外が入っていてもNaNにはならず、数字が続くところまでパースされる

という振る舞い確認されました。

所感

ユースケースによりますが、ユーザーの入力に対してparseInt(n, 10)をかけるときは、その前にnに対して正規表現で/^\d+$/などのチェックをしたほうが、成り行き感がなくなるのでより安心だと思いました。

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?