スポンサーリンク

JavaScriptの動かないコード (初級編) 数値判定の方法・・・入力値が有効な整数かどうかチェック


クイズ…下記のJavaScriptコードが,意図した動作をしないのはどうしてですか。(制限時間1分)


やりたい事

  • フォーム上で,テキストボックスに整数を入力してもらう。
  • 有効な整数かどうか,ページ上でバリデーションを行なう。
<input type="text" id="my_num">
<input type="button" onClick="f()" value="数値チェック">

<script language="JavaScript">
function f()
{
	var str_num = my_num.value;
	if (
		isNaN( parseInt( str_num ) )
		||
		isNaN( str_num )
	)
	{
		alert("有効な整数ではありません。");
	}
	else
	{
		alert("OK"); // 有効な整数が入力された
	}
}
</script>






発生する不具合

これだと," 1" (数字の前にスペースが入った文字列) や, "01" が通過してしまう。

  • isNaN( num )は,
    • "" を通してしまう。
    • " " を通してしまう。
    • " 1" を通してしまう。
    • "01" を通してしまう。
    • "1a" は通さない。
  • isNaN( parseInt( num ) )は,
    • " 1" を通してしまう。
    • "01" を通してしまう。
    • "1a" を通してしまう。
    • "1+1" を通してしまう。
    • "" は通さない。
    • " " は通さない。

落とし穴は,

  • isNaN()が空文字列やスペース単体を通してしまう事と,
  • parseInt()が文字列の途中で整数変換をやめてしまう事

か。

修正案

これを避けるためには,下記のように書く方法がある。

<input type="text" id="my_num">

<input type="button" onClick="f()" value="数値チェック">

<script language="JavaScript">
function f()
{
	var str_num = my_num.value;
	if (
		str_num.match(/[^0-9]/g)
		 // "", " ", " 1", "1a" をはじく。
		 // 単体では,"01" を通してしまう
		||
		parseInt(str_num, 10) + "" != str_num
		 // "01", "1 " など0付き・スペース付き文字列をはじく。
		 // 単体では,スペースのみの文字列は通してしまう
	)
	{
		alert("有効な整数ではありません。");
	}
	else
	{
		alert("OK"); // 有効な整数が入力された
	}
}
</script>

上記では,

  1. 正規表現を使って,まず1文字ずつが数字であるか,文字列として精査する。
  2. 1で漏らした非整数のケースとして,先頭の"0"をカットする。カットしてから,元の文字列と等しいかどうかを見る。

という手順を踏んでいる。


javascriptの正規表現の記法については,
http://pzxa85.hp.infoseek.co.jp/www/w...
を参照のこと。

Webアプリとしての注意点

ちなみに,JavaScriptで入力値の妥当性を検証するだけでは,Webアプリケーションとして不十分である。
送信面で見た極論で言うと

  • ブラウザとは,パケットを作ってサーバに送る手段のうちの1つであり
  • ブラウザ上で動くスクリプトとは,パケットを整形する手段のうちの1つである。(こういう見方はとても悲しいのだが。)

つまり,ブラウザ以外の手段でhttpリクエストを生成して送信すれば,ページ上でのバリデーションをかいくぐる事ができる。フォームにはどんな値でも入れてしまえる。
この事態を避けるためには,サーバ(cgi)側で入力値の検証を行なうようにすればよい。



関連する記事:

JavaScriptの動かないコード (中級編) nullが0以上0以下と認識されてしまう
http://language-and-engineering.hatenablog.jp/entry/20090906/p1


JavaScriptの動かないコード (中級編) 文字数のカウントに失敗する
http://language-and-engineering.hatenablog.jp/entry/20120523/LengthOfUnicodeS...


JavaScriptの動かないコード (中級編) かけ算を間違える
http://language-and-engineering.hatenablog.jp/entry/20080913/1221303278