今回はJavaScriptにおけるnullとundefinedの違いについて考察していきたいと思います。
こんな感じで記事を書いていますが自分もあまりよく分かっていないのが正直なところです。
あくまで考察ですが初学者の方には新しい知識を共有できる点があると思いますのでお話していきます。
また動画もあるので動画の方が見やすい方はどうぞ。
nullとundefinedは同じなのか?
まず初学者の方にはnullもundefinedも同じものに見えているかもしれません。
結論、同じに見えていて大丈夫です。
プログラミングあるあるなんですが細かいことに完璧な理解を求めると、勉強が進まず挫折してしまうんですよね。
そのためnullもundefinedもザックリ言うと「値がないもの」という風に思っておいてもらえればOKです。
そんな中で自分については少し深掘りしてみようと思います。
「nullとundefinedと言葉が分けられている以上は違いがあるんじゃないか?」と漠然と思ったからです。
試しにコンソールログで真偽値を真偽値をとって見ます。
console.log(null == undefined); // trueと出力される
するとtrueと出力されましたので、やはりnullもundefinedも同じものとして考えて良さそうです。
ちなみに厳格な不等号でも確認して見ます。
console.log(null === undefined); // falseと出力される
JavaScriptでは「===」とすることで「値と型が等しいか?」をチェックできます。
するとfalseと出力されたので、厳密には違うものらしいです。
この流れでそれぞれの型もチェックしておきましょう。
JavaScriptではtypeofを使うと型を調べることができます。
console.log(typeof null); // objectと出力される
console.log(typeof undefined); // undefinedと出力される
それぞれの型は別々でしたね。
undefinedの型がundefinedなのは想像ついたのですが、nullがオブジェクトとは思いませんでした。
「値がないオブジェクトがnull」とでも言うようです。
nullとundefinedはどちらを使うべきか?
厳密にはnullとundefinedは違うものということが分かりました。
そうすると実際のコードではどちらを使うのが良いんでしょうか?
現時点での自分の考えとしては、「どちらでも良い」と思っています。
APIコールで値がない場合に「nullが返ってくるAPI」「undefinedが返ってくるAPI」の両方がある以上、自分のコード上でどちらかに寄せることにあまりメリットを感じないからです。
と言っても自分なりに何となくの使い分けは持ってたりします。
一言で言うと「値をリセットするときはnullにする」って感じです。
例えば以下のように変数をグローバルで宣言します。
let test;
console.log(test); // undefinedと出力される
自分も今まで気にしたことが無かったのですが、変数の初期宣言をした場合には「undefined」になる仕組みらしいです。
単語の意味と同じで「定義されていないもの」ということだと思われます。
当たり前ですが変数に値をセットするとundefinedでは無くなります。
let test;
test = 100;
console.log(100); // 100と出力される
さらに同じような考えでnullをセットすると変数はnullになります。
let test;
test = null;
console.log(100); // nullと出力される
あくまで考察でしか無いですが、「既に値が入っているもの」「何かしら値が入る予定のもの」に対して中身のリセットをするときに「null」を使うんじゃ無いかと考えました。
「リセットであれば0や空文字では?」と思われた初学者の方がいるかもしれません。
確かに同じようなものだと考えることができますが、「0」「空文字」は文字や記号の中の1種類として用意されている以上は「0という値」「空文字という文字」となりそうです。
少し哲学的な話になってきましたが、実態の無いものとしてnullが用意されているように思えたからです。
長々と話してきましたが自分が話せるのはここまでです。
今後も新しい情報があれば改めて共有していきます。
ちなみにJavaScriptの生みの親であるブレンダン・アイクさんがTwitter上で本件についてコメントしているのを発見したので共有しておきます。
複数のリプライに分けて書かれていますが、だいたいが今日お話したことに近いようです。
追加情報としてJavaとJavaScriptの連携を想定していたことも影響しているようです。