大抵の、特に変数の型宣言を行わないタイプの言語では、型の異なる値の条件式は悩みの種です。
Javascriptもご他聞に洩れずというか、undefinedとnullが異なる分だけ更にややこしくなっているようです。
暗黙の型変換で痛い目にあわないよう、ちょっと実験してまとめてみます。
実験にはとりあえず、手っ取り早いので Jash を使用。
一緒に試してみるならば、こちらのBookmarkletをクリックしてコンソールに入力しながら読むとわかりやすいかもしれません。
nullとundefined
nullとundefined。たまに「同じもの?」と聞かれることもあるので、とりあえず確かめて見ます。
>> null==undefined true
あれ、同じでしょうか?
>> null===undefined false
もちろん違います。
しかし、== 演算子で比較する限りは「同じ」と言ってもよいようです。
では、実際は何が違うのでしょうか?typeofで確認してみます。
>> typeof null object >> typeof undefined undefined
nullはobjectなんですね。
根本的に型が違う(undefinedには型が無い?)ようです。
演算子: ==
ではこの == という曖昧な演算子について検証してみます。
登場人物はfalseと、それと等しくなりそうな7つの値「undefined」「null」「”(空文字)」「0(数値のゼロ)」「’0′(文字列としてのゼロ)」「”\n”(改行)」「” “(スペース)」。
先ほどのように、それぞれを == で結んでみましょう。
>> false==null false
全て試したマトリックスが次のものです。(undefはundefined)
false | undef | null | ” | 0 | ’0′ | “\n” | ” “ | |
---|---|---|---|---|---|---|---|---|
false | true | false | false | true | true | true | true | true |
undef | false | true | true | false | false | false | false | false |
null | false | true | true | false | false | false | false | false |
” | true | false | false | true | true | false | false | false |
0 | true | false | false | true | true | true | true | true |
’0′ | true | false | false | false | true | true | false | false |
“\n” | true | false | false | false | true | false | true | false |
” “ | true | false | false | false | true | false | false | true |
さて、いかがでしょう。
かなりの無秩序さにゲンナリです。
かろうじて文字列同士はキャストが行われない分だけ理解しやすいですが…つまり、ここで挙げた文字列は全てfalseや0と等価になるものの、お互いは等価にはならないと。
演算子: ===
では、型まで含めた === 演算子を用いた場合はどうでしょう。
>> false===0 false
これは、予想通り全ての異なる値間で false となりました。
厳密な比較を行うのならば、やはりこれを使うのが良さそうです。
演算子: !
では、if文の中での暗黙の条件式はではどうでしょう。
前項で false との等価比較だったので、あわせてここは「!」を付けた条件式に真と評価されるかどうかを試してみます。
わかりにくいですね。つまり例えば undefined のテストであれば、次のような式で試したということです。
>> (!undefined ? true : false) true
先ほどと同じ値を用いて試したのが、次の表です。
false | true |
---|---|
undefined | true |
null | true |
” | true |
0 | true |
’0′ | false |
“\n” | false |
” “ | false |
なんと、 == 演算子のどの列とも合致しない結果です。
つまり、こういうことなのですね。
>> hoge=null null >> (hoge==false?true:false) false >> (!hoge?true:false) true
まとめ
では、実際にはどうコーディングすれば安全なのでしょうか。
動きをある程度ちゃんと把握していれば、あとは用途にあわせて…という言い方に結局はなると思います。
しかし、型が怪しい場合は極力 == は使わない方が良いと言えそうです。
未定義の変数を調べる場合は typeof を使う
( typeof v == 'undefined' )
型を意識して正確に比較するなら === を使う
当然のことながら。
しかし実のところ、Javascriptでこういったケースはあまり多くないと思います。
テキストボックスに入力があるかを確かめる場合
これは、よく見ると結構難問です。
純粋に文字列が全く入っていないことを確かめるならば、=== を使えば確実です。
( text.value==='' )
しかし、必須入力確認をしたい場合、空白文字や改行が入っただけの状態は望ましくないはず。この条件では、そうした状態はパスしてしまいます。JavaScriptにはtrim関数が標準で無いので、これはそれなりに厄介。
では、意外とこれではどうでしょう。
( text.value==false )
こうすれば空白や改行は大丈夫ですが、「0」や「000」などと入力された場合に未入力と判定されてしまいます。
ここはやはり、正規表現などを用いるのが良さそうです。
まとめてみましたが、あんまりスッキリしませんでした。
Related posts:
参考になります。
しかし、
> ( text.value===” )
> しかし、この場合は空白や改行が入っただけでも条件をパスしてしまいます。
ん、そうはならないですよ。
このページのコメント欄(テキストボックスだと改行は無効になるのでテキストアリア)にコンソール上からid=”idid”として、
実際に空白文字と改行文字、それぞれについて比較してみましたが、
document.getElementById(“idid”).value===”";
false
両方共、当然ながらfalseが返ります。
僕が勘違いしてるのかしら・・・。
> 両方共、当然ながらfalseが返ります。
はい。その実行結果で合っています。表現が分かりにくかったですね。
通常、テキストボックに空白や改行だけが入った場合、それが必須入力項目であれば「何か入力された」とは見なしたくないと思います。しかし”===”で比較すると、そういった場合でもfalseが返って入力があったと見なされる(=条件をパスしてしまう)と表現しました。
レスありがとうございます!
そうですね、
> ( text.value===” )
このコードの前後が個人的にイマイチ繋がらなかったです><
認識としては
単純に、入力があったかどうかのチェックとしては
( text.value===” )
での評価結果が”trueの場合のみ”未入力と判定できる。他の場合は何かしらの入力がある。
で、よろしいですよね?
実際、この評価式としての返り値は、改行であろうが、空白文字であろうがfalseになりますから。
そうですね。
その「何かしらの入力」には、空白文字だったり改行も含まれてしまうということです。
わかりにくくて、申し訳ありません。
すみません、丁寧に答えて頂いてありがとうございました。
書籍化おめでとうございます。
ついにjQuery Mobileのリファレンスが出るんですねー、初期の頃、は少し癖があるということを聞いたことがあって触ってなかったんですが、今はそれだけ必要な技術になってきたんですねーw
色々参考にさせて頂きます。:D
こちらこそ、ありがとうございます。
> jQuery Mobile
確かにクセは強いですが、あれを自分でスクラッチから実装することを思えば
海外では使用実績が急増していますが、国内ではまだあまり聞きませんね。今後、増えていくんじゃないかと思っています。
指摘あった箇所の表現を変更しました。ありがとうございます。