文字列の配列 ['1', '2', '3']
の各要素を Array.map() で変換して、数値の配列 [1, 2, 3]
にしたい。
失敗例
['1', '2', '3'].map(parseInt);
上記の戻り値は、 [1, NaN, NaN]
になってしまう。原因は後述。
結論
小数や指数を含んでもよい場合
['1', '2', '3'].map(Number);
int限定の場合
['1', '2', '3'].map( str => parseInt(str, 10) );
参考
parseInt() のドキュメント
Array.map() のドキュメント (「トリッキーな使用例」の項)
上記のインスパイア元のブログ
以下は、参考ページの内容を自分なりに解釈・要約したものです。
正確な内容は上記ページをご参照ください。
parseInt ではだめな理由
前提1 Array.map()の仕様
構文
var new_array = arr.map(function callback(currentValue[, index[, array]]) {} )
引数
- callback:
新しい配列の要素を生成するための関数。次の3つの引数を取る。 - currentValue:
現在処理中の要素の値。 - index:
現在処理中の要素の配列内におけるインデックス。 - array:
map が実行されている配列。
戻り値
与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列。
前提2 parseInt() の仕様
構文
parseInt(string, radix);
引数
- string:
解析する値。引数stringが文字列でなければ、(抽象操作ToStringにより)文字列に変換される。 - radix:
2から36までの整数で、前述の文字列に対する基数(数学的記数法の底)を与える。基数が与えられない場合、通常は10。
戻り値
与えられた文字列を解析した整数値。最初の文字を数値に変換できない場合、NaN が返される。
つまり?
['1', '2', '3'].map(parseInt);
上記のように記述してしまうと、実際の parseInt() の呼び出しは下記のようになる。
parseInt("1", 0); // 第2引数はデフォルトの10になる※
parseInt("2", 1); // 1が基数として渡されるためNaNが返る
parseInt("3", 2); // 2が基数として渡され、"3"は2進数として解析できないためNaNが返る
※parseInt() のドキュメントより、第2引数が0のときの基数は10とは限らない。
第2引数のradixがundefinedか0の(または与えられていない)場合は、JavaScriptはつぎのように解釈します。
- 第1引数のstringが「0x」または「0X」で始まるときは、第2引数のradixは16(16進法)としてその後の文字列を解析します。
- 第1引数のstringが「0」で始まるときは、第2引数のradixは8(8進法)または10(10進法)とされます。厳密には、基数がどちらになるかは実装によります。ECMAScript 5 の仕様では10(10進法)です。ただし、まだすべてのブラウザがサポートしている訳ではありません。したがって、parseInt()関数を使うとき基数は必ず与えてください。
- 第1引数のstringがその他の値で始まるときは、第2引数のradixは10(10進法)とされます。
(蛇足)配列の値によっては下記のようになる。
["0XFF","2","10"].map(parseInt); // 戻り値は [255, NaN, 2]( 16進数、NaN、2進数)
parseIntを使うなら
ファンクションを別途定義する。
function returnInt(element) {
return parseInt(element, 10); // 第二引数を明示する
}
['1', '2', '3'].map(returnInt); // [1, 2, 3]
アロー関数を使うと短く書ける。
['1', '2', '3'].map( str => parseInt(str, 10) ); // [1, 2, 3]
渡す値が決まっているならNumberオブジェクトを使うのが一番簡潔。
['1', '2', '3'].map(Number); // [1, 2, 3]
// 小数表現や指数表現も解釈できる(してしまう)
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]