2014

12

13

JavaScriptのnullとundefinedの区別と使い分けをまとめてやんよ

Pocket
LINEで送る
Facebook にシェア
reddit にシェア
LinkedIn にシェア

他人が作ったJavaScriptでイベント処理など解析していると必ず出てくる
nullundefined。 コレの違いを聞くと必ず言われる「ggれks」。
て事で調べようジャマイカ。

「何もない」という表現の由来

nullundefinedの意味としてよく表現される「何もない」

多くのプログラミング言語では、何もないことを1つの値で表現します。

例えば、Javaならnull、Rubyならばnilなど。
C言語のような古い言語には特別な値を用意する代わりに「0」などの値を「NULL」と扱うという約束事が存在し、関数型言語の祖であるLispは「空リスト(要素がないリスト)をnullとして扱います

言語ごとの「何もない」を表す方法

Lisp()空のリストをnullと見なす
C言語0NULLを表す
特別な値がないので0をNULLと見なす
Javanull最近の言語には特別な値が用意されている
Rubynil最近の言語には特別な値が用意されている
JavaScriptnull
undefined
2つの値がある

Javaのnullのように、特別な値を言語側が提供しなくても、一定の約束事(0NULLとするなど)を決めることで対応できるのです
逆にいえば、約束事を決めておいてでも、“何もない値"を使う必要があったわけです。

「何もない」を表現する必要性とは?

値を格納する箱に名前を付けるもの、あるいは値を束縛するために必要な物が変数

変数は基本的には何かの値とひも付いている物であり、逆に値とひも付かない変数があってもよいのでは?
これこそがnull」が必要とされた理由です。

ネット検索に例えて考えてみる

極端な例でいうならば、とあるキーワードをネットで検索した場合、
キーワードに該当するサイトやページがヒットすれば検索サイトはその該当するページを一覧で返してくれますが、
もしキーワードに該当するページが無かった場合、何の反応もしないわけにはいきませんから
システムエラー画面ではなく「何もなかった」という事実を返すべき結果を示すためにnullを使う必要性があるんですね。

多くの言語では、変数の初期値として利用する、関数の返り値に値がなかったことを表す、といった目的でnullが利用されているのです。

「null」と「undefined」の「何もない」の区別

「undefined」は未定義であること

JavaScriptでは、undefinedによって変数の初期値が定義されていないことを表します

①変数を初期化せずに出力

var yanyo;	//変数yanyoを定義
print(yanyo);	//変数yanyoを出力

この処理を実行するとundefinedが結果として返されます。

yanyo変数は宣言されているが、値が何も指定されていないので、
言語の初期値である未定義な値「undefinedが入っているということです

②初期値を持たないプロパティを出力する

var obj = {};
print(obj.hoge);	//「undefined」

この処理を実行しても①と同じくvar変数のみならず、オブジェクトのプロパティも同様に「undefinedが適用されます

JavaScriptでは、いきなりプロパティを利用できますが、初期値が入っていない場合はundefinedが使われるのです。

「null」は該当する値がないこと

先ほど例えたネット検索の場合で例えると、該当するキーワードがない場合は何が返るのでしょうか?
上記のような処理で未定義を表すためにundefinedが使われていましたが、関数の返り値がundefined(未定義)では少し違和感があります。
たまたまそのデータベースではキーワードに該当するページが見つからなかっただけであって、決して「未定義」ではないはずです。
このような場合は、nullの方がしっくりくると思います。

③該当しない値を出力する

JavaScriptの定番操作であるHTMLのノードを取得する関数を実行してみましょう。

アナタの作ったページにid="yanyo"というHTML中にない(そんなIDは付けないハズ)yanyoノードを指定してみましょう。

document.getElementByld('yanyo')

実行すると、getElementByld関数は「undefined」ではなく「null」を返します
つまり該当する値がないことを「nullで表現しているわけです。

関数が「undefined」を返す場合

④何も処理を行わない関数を出力する

function funcYanyo(){ }		//プ口パティを持たないオブジェクト
funcYanyo();	//「undefined」

funcYanyo関数の中身が空なので、何も実行しない、何も返さない関数になります
何も処理を記述していない関数の返り値は「undefinedとなります。

なぜJavaScriptでは「何もない」が2種類ある?

JavaScriptでは、関数を実行する際に必ず返り値を指定しなければなりません。
この中身が空の関数は、undefinedを返すことになります。
関数が返すものを定義していないので、undefinedが返るわけです。

他の言語では、返り値を返すはずなのに何も返さない場合、nullを返したり、
あるいは「何も返さない関数」であることを明示的に宣言したりする必要があります。

Javaなどの言語では、voidで宣言する必要があります。
このようにJavaScriptでは、
未定義であること(undefined)」と「該当する値がないこと(null)」
を区別しているので2つの値が存在するのです。

「null」と「undefined」の用途がハッキリしない理由

これだけ明確な区別をしておきながら、使う側がいまいち2つの用途を聞いたり調べるまでハッキリしない理由をまとめてみました。

理由① 未定義と該当値が無いことを区別したい場合が少ない

どっちかよくわかんなくてもエラーで停止しなければなんとなく良しとされる風潮。

理由② 変数にundefinedを代入することができてしまう

yanyo = undefined;
alert(yanyo); 	//「undefined」
未定義としての意味の「undefined」なのか?
誰かの思惑で意図的に代入された値が「undefined」なのか?
出力結果としてはどちらの意味でも同じ「undefined」が出力できるので、ソースを読み解かなければ判断できない(こんなケースはよほど闇を抱えたチーム環境でもなければまず無いはずですが・・・)

理由③ 等価演算子で比較判定するとどちらも「true」

var yanyo = undefined;
alert(yanyo == null); // 「true」
alert(yanyo === null); // 「false」

厳密等価演算子(===)まで比較すれば型が違う(false)と判定されるが、
等価演算子(==)で「null」と「undefined」2つを判定すると「true」が返ってしまうのでとりあえず同じ物として認識される

JavaScriptでは「偽」の扱いが複雑

!演算子を使って真偽値を反転

!false;		// 「true」
!null;		// 「true」
!undefined;	// 「true」

真偽値を反転させる演算子の「!」を使うと、「null」も「undefined」も「false」と同じ扱いになりますが・・・

「null」と等価演算子比較する

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・・・

Pocket
LINEで送る
Facebook にシェア
reddit にシェア
LinkedIn にシェア

トップへ