JavaScriptのArray.prototype.mapメソッドは、各要素に対してコールバック関数を実行し、その戻り値で構成される新規配列を返します。このとき、コールバック関数には自動的に3つの引数が渡されます:現在の要素、インデックス、元の配列。この仕様が、グローバル関数をそのまま渡す場合に予期せぬ挙動を引き起こすことがあります。
parseIntの2番目の引数がインデックスとして解釈される問題
parseIntは文字列と基数(radix)の2つの引数を受け入れる関数です。しかし、['10', '20', '30'].map(parseInt)のように直接渡すと、mapが渡す第2引数(インデックス)が基数として解釈されてしまいます:
['10', '20', '30'].map(parseInt);
// 実際には以下のように評価される:
// parseInt('10', 0) → 10(基数0は10進数とみなされる)
// parseInt('20', 1) → NaN(基数1は無効)
// parseInt('30', 2) → NaN('30'は2進数では不正)
結果として[10, NaN, NaN]が得られ、意図した[10, 20, 30]とは異なります。安全な書き方は、明示的に基数を指定したアロー関数を使うことです:
const strings = ['10', '20', '30'];
const numbers = strings.map(s => parseInt(s, 10)); // [10, 20, 30]
parseFloatは引数の過剰を無視するため比較的堅牢
parseFloatは基数を扱わず、最初の文字列引数のみを対象とします。残りの引数(インデックス・配列)は無視されるため、mapとの組み合わせでも安定して動作します:
['3.14', '2.71', '1.41'].map(parseFloat); // [3.14, 2.71, 1.41]
ただし、これはparseFloatの実装依存の振る舞いであり、明示的なラップが保守性を高めます。
Numberコンストラクタは単一引数に最適化されている
Numberは型変換専用の関数で、第2引数を無視します。そのため、mapのシグネチャと自然に適合し、最も推奨されるパターンです:
['100', '200', '300'].map(Number); // [100, 200, 300]
['true', 'false', ''].map(Number); // [1, 0, 0]
[null, undefined, '42'].map(Number); // [0, 0, 42]
このように、Numberは型変換の意図を明確にし、余分な引数による副作用を回避できます。