JavaScriptはスクリプト言語で、暗黙的型変換をおこなってくれるプログラミング言語になります。
暗黙的型変換は便利ですが、思いもよらぬバグを作りこむことがあります。
本記事では、筆者が暗黙的型変換でハマったバグについて紹介し、正解となるプログラミングについて説明していきます。
目次
暗黙的型変換とは
そもそも、暗黙的型変換とはいったいどういう変換なのでしょうか?
JavaScriptの型変換には、暗黙的変換と明示的変換の2つがあります。
暗黙的変換とは、”=”で連結された値の中で、どちらかの値の型に合わせる形で変換がおこなわれます。
var num = '1'; var value = num;
この時、変数valueはString型の”1″が格納されます。
しかし、この暗黙的型変換は、しばしば直感的には解りにくい型変換をおこない、非常に解りにくいバグを作りこむことがあります。
プログラマーとしては便利な仕組みなのですが、注意が必要です。
明示的変換とは、プログラムの中で型変換処理を記載して変数宣言する方法です。
var num = Number('1'); var value = num;
この時、valueはNumber型の”1″が格納されます。
型変換をおこなう代表的な関数
暗黙的型変換は、便利な反面、非常に解りにくいバグを作りこむことがあります。
可能な限り、型を意識してプログラミングをしようとした場合に、型変換をおこなう関数を使用することになります。
型変換をおこなってくれる代表的な関数を紹介していきます。
Number(数値に変換)
「Number」は、文字列を数値に変換する関数です。
var num = Number('12345'); var value = num;
valueは数値の12345になります。
parseInt(基数を指定して数値に変換)
「parseInt」は、「Number」と同様に、文字列を数値に変換する関数です。
「Number」との違いは、基数を設定できる点です。
var num = parseInt('12345', 10); var value = num;
valueは数値の12345になります。
10は10進数を指定しています。
var num = parseInt('A', 16); var value = num;
この場合は16進数での変換となるので、valueは10です。
String(文字列に変換)
「Number」は、数値を文字列に変換する関数です。
var num = String('12345'); var value = num;
valueは文字列の12345になります。
暗黙的変換が作りこむバグ
型を意識せずにプログラミングした結果、筆者が作りこんでしてしまったバグの例を紹介します。
以下、サンプルプログラムです。
// 開始Idxと終了Idxを取得 var startIdx = document.getElementById("startIdx").value; var endIdx = document.getElementById("endIdx").value; // 取得数分ループ for (var lc = startIdx; lc < endIdx; lc++) { console.log("lc=" + lc); }
startIdxと1、endIdxが10の結果は以下です。
正解です。
lc=1 lc=2 lc=3 lc=4 lc=5 lc=6 lc=7 lc=8 lc=9 lc=10
startIdxと101、endIdxが110の結果は以下です。
これも正解です。
lc=101 lc=102 lc=103 lc=104 lc=105 lc=106 lc=107 lc=108 lc=109 lc=110
startIdxと91、endIdxが100の結果はどうでしょう?
何も表示されません。
つまり、ループに入らないです。
91の文字列を100の文字列でループしてしまっているため、文字コードとしては91より100の方が小さいために、このバグが発生します。
「document.getElementById()」は、HTML内にある値を取得する関数ですが、この際、文字列として数値を取得します。
正解のプログラムとしては以下になります。
// 開始Idxと終了Idxを取得 var startIdx = documentGetelementId("startIdx"); var endIdx = documentGetelementId("enddx"); // 数値に変換 startIdx = Number(startIdx); endIdx = Number(endIdx); // 取得数分ループ for (var lc = startIdx; lc < endIdx; lc++) { console.log("lc=" + lc); }
for文のループは数値全体の処理になっているので、開始位置と終了位置は、いったん数値に変換するのが正解、ということになります。
数値変換処理をおこなうようにして修正したプログラムの実行結果は、startIdxと91、endIdxが100の場合は以下結果になります。
正解の結果ですね。
lc=91 lc=92 lc=93 lc=94 lc=95 lc=96 lc=97 lc=98 lc=99 lc=100
まとめ
暗黙的型変換は便利ですが、思いもよらぬバグを作りこむ要因をはらんでいます。
場面によって、きちんと型変換をおこなってプログラミングするようにしましょう。