🕵️

【TypeScript】nullとundefinedを改めて整理する

2022/07/18に公開

どうもフロントエンドエンジニアのoreoです。

この記事ではnullとundefinedの違いについて整理します。人に説明する時に違いがパッと思い出せなかったので、忘れないように書きたいと思います。

1 nullとundefinedについて

nullとundefinedは、それぞれ「データがない」ことを意味するプリミティブです。それぞれnull、undefinedという値と型をもちます。

2 null vs undefined

2-1 発生のタイミング

nullは基本的に自然発生しないので、意図を持って代入することが必要です(※)。

一方で、undefinedは、自然に発生するもので、例えば変数宣言時に初期化しなかった場合、オブジェクト・配列の存在しないプロパティ・要素にアクセスした場合などに、undefinedになります。

(※)一部のDOM系のAPIはnullを返す時があるのでライブラリのよってはnullを返すことがあります。

//変数宣言時に初期化しない場合
let test;
console.log(test); //undefined

//オブジェクト・の存在しないプロパティにアクセスした場合
let Obj = { test: "test" };
console.log(Obj.test2); //undefined

//配列の存在しないい要素にアクセスした場合
let Array = ["test"];
console.log(Array[1]); //undefined

//返り値の無い関数の場合
function func() {
  console.log("test");
}
console.log(func()); //undefined

2-2 変数としての扱い

nullはリテラルな一方で、undefinedは変数。

let null; //エラー「Unexpected token」!!

undefinedは変数なので書き換えることが可能。

console.log(undefiend); //undefiend

let undefiend = "test";
console.log(undefiend); //test

2-3 typeof演算子の結果

typeof演算子は、typeof 式のような形で式を評価し、その評価結果に応じて以下表「結果」のような文字列を返します。nullの場合は、”object”を返し、undefinedの場合は、”undefined”を返します。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof

2-4 等価演算子と厳密等価演算子

等価演算子は、nullとundefinedを比較した時に、trueを返します。一方で、厳密等価演算子は、nullとundefinedを比較した時に、方が異なるのでfalseを返します。

//等価演算子
console.log(null == null);//true
console.log(null == undefined);//true
console.log(undefined == undefined);//true

//厳密等価演算子
console.log(null === null);//true
console.log(null === undefined);//false!!!!
console.log(undefined === undefined);//true

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Equality

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Strict_equality

2-5 JSON.stringify()

JSON.stringify()は、オブジェクトや値をJSON文字列に変換してくれます。オブジェクトのプロパティにnullが存在していた場合は、JSON文字列に変換されるが、undefinedが存在していた時にJSON文字列に変換されず、そのプロパティは削除さる。

//オブジェクトでJSON.stringify()を使用した場合
//undefinedのプロパティは削除される
let nullObj = {
  test: null
};
let undefinedObj = {
  test: undefined
};
console.log(JSON.stringify(nullObj)); //{"test":null}
console.log(JSON.stringify(undefinedObj)); //{}

//配列でJSON.stringify()を使用した場合
//配列では、undefinedの要素は削除されない
let nullArray = [null, "test"];
let undefinedArray = [undefined, "test"];
console.log(nullArray); //[null, "test"]
console.log(undefinedArray); // [undefined, "test"]

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

3 nullとundefinedのどちらを使うのか?

状況によって違うので一概には言えませんが、undefinedが推奨されています(TypeScriptのコーディングガイドラインにもその旨の記載あり👇)。チームルールとして、どちらかに寄せていく場合は、undefinedはさまざまな場面で発生する為、undefiendに寄せる方が簡単という考え方もある模様です。

https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#null-and-undefined

4 最後に

JSON.stringify()の挙動は初めて知りました。この記事で取り上げた以外にも細かい違いがあると思いますが、2-1の発生のタイミングや3の使い分けに関しては、押さえておきたいですね!

5 参考

https://gihyo.jp/book/2022/978-4-297-12747-3
https://typescriptbook.jp/reference/values-types-variables/undefined-vs-null

Discussion