4
0

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]Array.mapとparseIntの組み合わせの落とし穴

Last updated at Posted at 2020-08-01

どうも、えいやです。

JavaScriptのよくある落とし穴の話をします。

例えば、'01:24'のような時刻表示について、時間と分をintで取ろうと以下のようなコードを書いたとします。

fig.1.1
'01:24'.split(':').map(parseInt)

実はこれは正常に動きません。結果は以下となります。

fig.1.2
> '01:24'.split(':').map(parseInt)
[ 1, NaN ]

試しに:区切りとなっている文字列で与えられている数値の数を増やすと、以下のようになります。

fig.2
% node -v && node
v12.16.3
> '01:02:03:04:05:06'.split(':').map(parseInt)
[ 1, NaN, 0, 0, 0, 0 ]

さて、何が起きているのか正確にわかりますか?

とりあえず意図通りに動かすには、mapが引数として取る関数に引数を与えて、

fig.3
> '01:02:03:04:05:06'.split(':').map(n=>parseInt(n))
[ 1, 2, 3, 4, 5, 6 ]

とします。

引数を設定するかどうかで動作が変わるので、原因は引数です。

特にScalaなどの他の言語をやっていると見落としがちですが、Array.mapの引数となる関数が取る引数ですが、実は以下のようになっています。

fig.4.1
Array.map((currentValue, index, array)=>...);

具体的になにが来ているのかは、こうすると分かりやすいです。

fig.4.2
> '01:02:03:04:05:06'.split(':').map(console.log)
01 0 [ '01', '02', '03', '04', '05', '06' ]
02 1 [ '01', '02', '03', '04', '05', '06' ]
03 2 [ '01', '02', '03', '04', '05', '06' ]
04 3 [ '01', '02', '03', '04', '05', '06' ]
05 4 [ '01', '02', '03', '04', '05', '06' ]
06 5 [ '01', '02', '03', '04', '05', '06' ]

parseIntは、第2引数に基数をとりますので、先程の例ではindexの値が当てられて順に0,1,2,3,4,5進数として文字列を数値変換していたようですね。

それを踏まえてfig.2の振る舞いを見てみましょう。引数が0のときはどうやら10進数と解釈されている様子です。で、"1進数"は常にNaN。その他の進数では、範囲外の数字が使用されている部分を無視して先頭の0だけを解釈しているようです。

JavaScriptを始めとした型の判定が甘い言語では、こうしたうっかりミスを起こしがちなので注意しましょう。

4
0
0

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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?