プログラムを書いているとよくエラーが起きます。
エラーが起きないように修正していくことでプログラムが完成します。
困るのはエラーが起きないのに意図通りに動かない場合です。これは原因を探るのが難しいです。
もっと困るのは「このように動くはずだ」と思い込んでいる場合です。
JavaScriptには、このような「仕様」がいくつかあります。初心者が陥りそうなケースを挙げてみます。
parseIntの引数を省略する
文字列を整数に変換するときに「parseInt」を使います。
「parseInt(文字列,基数)」のように使い、基数に指定した進数で変換します。例えば「16」を指定すると16進数になります。
基数を省略すると10進数になりますが、恐ろしいことに文字列の先頭が「0」(ゼロ)のときは8進数になります。
alert(parseInt(a));
この場合、先頭が「0」なので「10」を8進数で解釈するので「8」に変換されます。「15」ならば「13」になります。必ず基数を指定して「parseInt(a, 10)」のようにするのが確実なようです。
2013年8月4日追記
コメントをいただきました。ECMAScript5で8進数としての解釈を許す表現が仕様から削除されたそうです。
parseInt – JavaScript | MDN
2022年2月4日追記
parseInt(0.0000005) が 5 になるケースがあります。途中で 5e-7 に変換されるからだそうです。
Math.trunc を使うとよいです。
文字列にプラスを付けて整数にする
数を表す文字列の前に「+」(プラス)を付けると数値に変換されます。
しかし注意しないと数値に変換されません。
b = "013";
alert(+a+b);
「28」になることが期待されますが、実際は「15013」になります。
「+a」で「15」という数値に変換されたものの「15+”013″」となってまた文字列に戻ってしまうのでしょう。
「alert(+a + +b)」または「alert(+ a + + b)」のように、間に加算のための「+」が必要です。見にくいので誤りの原因になりそうです。
このように計算式で使うときは一度、変数に代入するか、「parseInt」を使うのが無難でしょう。
配列の要素をlengthで数える
配列の要素を数える場合には「length」を使いますが、実際に数えているわけではありません。
x[0] = 12;
x[2] = 13;
alert(x.length);
添え字が0の場合と2の場合だけ代入したのだから「2」になることが期待されますが、実際は「3」になります。
添え字が数字のときは最大の数字の次の数が返ります。
x["dog"] = 14;
alert(x.length);
添え字が文字列の場合は「0」になります。
sortの比較関数を省略する
配列をソートする場合は「sort」を使いますが、比較関数を与えない場合は、数値ではなく文字列としてソートしてしまいます。
x = [10, 8, 6, 12];
x.sort();
alert(x);
「10,8,6,12」をソートするのだから「6,8,10,12」となることが期待されますが、実際は「10,12,6,8」になります。
1桁目の「1,8,6,1」を比較し、次に2桁目を比較するという「辞書的」なソートになります。
数値として昇順にソートするには比較関数として
a>bならば0より大きい値
a==bならば0
a<bならば0より小さい値
を返す関数を指定します。降順はこの逆です。
単なる数値の比較ならば
a-b
を返せばよいでしょう。
x = [10, 8, 6, 12];
x.sort(function(a, b){
return a - b;
});
alert(x);
配列変数を別の変数に代入する
ある配列変数があって、例えば、これをソートしたいけれど元の配列も残したい、というようなケースがあったとします。
そこで、元の配列変数を新しい配列変数に代入します。
新しい配列変数をソートしたり加工したりしても、元の配列変数は変わらないことが期待されますが、実際は新しい配列変数と同じになります。
x = [1, 3, 4, 2];
y = x;
y.sort();
alert(x);
alert(y);
この場合、xもyも「1,2,3,4」になります。
直接、代入するのではなく、「slice」を使うとよいです。
x = [1, 3, 4, 2];
y = x.slice();
y.sort();
alert(x);
alert(y);
xは「1,3,4,2」のままですが、yは「1,2,3,4」になります。
コメント
parseIntはES5で8進数リテラルを解釈しないようになりました
もう心配はいりません
また、ES6で新しい8進数リテラルが定義されました
>MOSAさん
ご指摘、ありがとうございます。
以前、実際にこれにはまって困ったことがありましたので、例として挙げました。以来、第2引数をセットするように注意していたのですが、今、Chromeで試したら第2引数を省略しても意図通り解釈しました。仕様としてはこちらの方がいいですね。