他人が作ったJavaScriptでイベント処理など解析していると必ず出てくる
null
とundefined
。
コレの違いを聞くと必ず言われる「ggれks」。
て事で調べようジャマイカ。
nullとundefinedの意味としてよく表現される「何もない」。
多くのプログラミング言語では、何もないことを1つの値で表現します。
例えば、Javaならnull
、Rubyならばnil
など。
C言語のような古い言語には特別な値を用意する代わりに「0」などの値を「NULL」と扱うという約束事が存在し、関数型言語の祖であるLispは「空リスト(要素がないリスト)をnull
として扱います
Lisp | () | 空のリストをnullと見なす |
---|---|---|
C言語 | 0 | NULLを表す 特別な値がないので0をNULLと見なす |
Java | null | 最近の言語には特別な値が用意されている |
Ruby | nil | 最近の言語には特別な値が用意されている |
JavaScript | null undefined | 2つの値がある |
Javaのnull
のように、特別な値を言語側が提供しなくても、一定の約束事(0
をNULL
とするなど)を決めることで対応できるのです
逆にいえば、約束事を決めておいてでも、“何もない値"を使う必要があったわけです。
値を格納する箱に名前を付けるもの、あるいは値を束縛するために必要な物が変数。
変数は基本的には何かの値とひも付いている物であり、逆に値とひも付かない変数があってもよいのでは?
これこそが「null
」が必要とされた理由です。
極端な例でいうならば、とあるキーワードをネットで検索した場合、
キーワードに該当するサイトやページがヒットすれば検索サイトはその該当するページを一覧で返してくれますが、
もしキーワードに該当するページが無かった場合、何の反応もしないわけにはいきませんから
システムエラー画面ではなく「何もなかった」という事実を返すべき結果を示すためにnull
を使う必要性があるんですね。
多くの言語では、変数の初期値として利用する、関数の返り値に値がなかったことを表す、といった目的でnull
が利用されているのです。
JavaScriptでは、undefined
によって変数の初期値が定義されていないことを表します
var yanyo; //変数yanyoを定義 print(yanyo); //変数yanyoを出力
この処理を実行するとundefined
が結果として返されます。
yanyo
変数は宣言されているが、値が何も指定されていないので、
言語の初期値である未定義な値「undefined
」が入っているということです
var obj = {}; print(obj.hoge); //「undefined」
この処理を実行しても①と同じくvar変数のみならず、オブジェクトのプロパティも同様に「undefined
」が適用されます
JavaScriptでは、いきなりプロパティを利用できますが、初期値が入っていない場合はundefined
が使われるのです。
先ほど例えたネット検索の場合で例えると、該当するキーワードがない場合は何が返るのでしょうか?
上記のような処理で未定義を表すためにundefined
が使われていましたが、関数の返り値がundefined
(未定義)では少し違和感があります。
たまたまそのデータベースではキーワードに該当するページが見つからなかっただけであって、決して「未定義」ではないはずです。
このような場合は、nullの方がしっくりくると思います。
JavaScriptの定番操作であるHTMLのノードを取得する関数を実行してみましょう。
アナタの作ったページにid="yanyo"
というHTML中にない(そんなIDは付けないハズ)yanyo
ノードを指定してみましょう。
document.getElementByld('yanyo')
実行すると、getElementByld
関数は「undefined
」ではなく「null
」を返します。
つまり該当する値がないことを「null
」で表現しているわけです。
function funcYanyo(){ } //プ口パティを持たないオブジェクト funcYanyo(); //「undefined」
funcYanyo
関数の中身が空なので、何も実行しない、何も返さない関数になります
何も処理を記述していない関数の返り値は「undefined
」となります。
JavaScriptでは、関数を実行する際に必ず返り値を指定しなければなりません。
この中身が空の関数は、undefined
を返すことになります。
関数が返すものを定義していないので、undefined
が返るわけです。
他の言語では、返り値を返すはずなのに何も返さない場合、null
を返したり、
あるいは「何も返さない関数」であることを明示的に宣言したりする必要があります。
Javaなどの言語では、void
で宣言する必要があります。
このようにJavaScriptでは、
「未定義であること(undefined)」と「該当する値がないこと(null)」
を区別しているので2つの値が存在するのです。
これだけ明確な区別をしておきながら、使う側がいまいち2つの用途を聞いたり調べるまでハッキリしない理由をまとめてみました。
どっちかよくわかんなくてもエラーで停止しなければなんとなく良しとされる風潮。
yanyo = undefined; alert(yanyo); //「undefined」未定義としての意味の「
undefined
」なのか?undefined
」なのか?undefined
」が出力できるので、ソースを読み解かなければ判断できない(こんなケースはよほど闇を抱えたチーム環境でもなければまず無いはずですが・・・)
var yanyo = undefined; alert(yanyo == null); // 「true」 alert(yanyo === null); // 「false」
厳密等価演算子(===
)まで比較すれば型が違う(false
)と判定されるが、
等価演算子(==
)で「null
」と「undefined
」2つを判定すると「true
」が返ってしまうのでとりあえず同じ物として認識される
!false; // 「true」 !null; // 「true」 !undefined; // 「true」
真偽値を反転させる演算子の「!
」を使うと、「null
」も「undefined
」も「false
」と同じ扱いになりますが・・・
null == false; // 「false」 undefined == false; // 「false」
「!false
」と「!null
」は同じ「true
」でしたが、等価演算子で比較すると「null
」と「false
」は違う「false
」と判定されてしまいます。
比較元/対象 | false | 0(数値) | '0' (文字列) |
'_' (空文字) |
' ' (空白) |
'\n' (改行) |
---|---|---|---|---|---|---|
false | true | true | true | true | true | true |
0(数値) | true | true | true | true | true | true |
'0'(文字列) | true | true | true | false | false | false |
'_'(空文字) | true | true | false | true | false | false |
' '(空白) | true | true | false | false | true | false |
'\n'(改行) | true | true | false | false | false | true |
一覧でわかるようにある操作では偽になるものが別の操作では偽(false
)ではないのです。
「undefined
」と「null
」。それぞれの概念はわかりましたが、いざ使いこなすとなるとまだまだ修行が必要な様です。
「JavaScriptはHTMLの埋め込み型の言語であって実行するブラウザによって動作が異なるスクリプトだから他の言語(特にJava)と一緒のプログラム扱いすんじゃねぇ!!」
という主張を聞いたことがありますが、他の言語を知っている人から見ればやはり特殊なんだなJavaScript・・・