多くの他のプログラミング言語とは対照的に、JavaScriptには(意味のある)値が存在しないことを表す2つの異なるものがあります。
nullとundefinedです。
プリミティブ値nullは、変数に対して意図的に「空の値」として使われます。
他の言語では、同様の仕組みが(存在しない)オブジェクトやポインター型にだけ使われることがあります。
JavaScriptでは、nullはあらゆる型に対して空の値を表すのが一般的です。
let name = null;
// name is intentionally set to "empty" because it is not
// available
変数がnullかどうかは、厳密等価演算子===を使って確認できます。
nullはプリミティブ値ですが、typeof演算子は歴史的な理由から「誤って」objectを返します。
つまり、これだけでは変数がnullかどうかを確認するのに使えません。
let name = null;
name === null;
// => true
// Pitfall:
typeof name;
// => 'object'
値を代入されていない変数の型は
undefinedです。1
つまり、nullが空の値(ただし値ではある)を表すのに対し、undefinedは値が完全に存在しないことを表します。🤯
undefinedはさまざまな場面で現れます。
undefinedです。undefinedになります。undefinedです。undefinedになります。let name;
console.log(name);
// => undefined
let obj = { greeting: 'hello world' };
console.log(obj.missingKey);
// => undefined
function returnNothing() {
return;
}
console.log(returnNothing());
// => undefined
変数がundefinedかどうかは、厳密等価演算子===またはtypeof演算子を使って確認できます。
let name;
name === undefined;
// => true
typeof name === 'undefined';
// => true
変数に手動でundefinedを代入することはおすすめしません。空の値を意図的に設定したことを明確にするために、代わりに常にnullを使いましょう。
前述のとおり、JavaScriptでは、オブジェクトに存在しないキーにアクセスするとundefinedが返されます。
しかし、入れ子になった値を取得しようとして親のキーが存在しない場合、入れ子のキーの評価はundefinedに対して行われ、TypeError: Cannot read property ... of undefinedにつながります。
理論上は、入れ子のキーを取得しようとする前に、必ず親のキーが存在するかを確認する必要があります。
以前はよくAND演算子&&でこれを行っていましたが、深く入れ子になった値では、これは非常に長い式になってしまいます。
obj.level1 && obj.level1.level2 && obj.level1.level2.level3;
この問題を解決するために、オプショナルチェイニングが2020年に言語仕様に追加されました。
オプショナルチェイニング演算子?.を使うと、親がnullまたはundefinedでない場合にだけ、JavaScriptが入れ子のキーにアクセスしようとするようにできます。
それ以外の場合はundefinedが返されます。
const obj = {
address: {
street: 'Trincomalee Highway',
city: 'Batticaloa',
},
};
obj.residence;
// => undefined
obj.address.zipCode;
// => undefined
obj.residence.street;
// => TypeError: Cannot read property 'street' of undefined
obj.residence?.street;
// => undefined
obj.residence?.street?.number;
// => undefined
変数がnullまたはundefinedだった場合にデフォルト値を適用したい、という場面があります。
以前は、三項演算子?を使ったり、OR演算子||の遅延評価を利用したりして、これを行うことがよくありました。
これには、変数がnullまたはundefinedのときだけでなく、変数がfalsyである(例えば''や0)すべての場合にデフォルト値が適用されるという欠点があります。
これは簡単に予期しない結果を引き起こす可能性があります。
let amount = null;
amount = amount || 1;
// => 1
amount = 0;
amount = amount || 1;
// => 1
amount = 0;
amount ? amount : 1;
// => 1
これを解決するために、Null合体演算子??が導入されました。
オプショナルチェイニングと同様に、これは2020年に言語仕様に追加されました。
Null合体演算子??は、左辺のオペランドがnullまたはundefinedのときにだけ、右辺のオペランドを返します。
それ以外の場合は、左辺のオペランドが返されます。
これにより、デフォルト値をより正確に適用できるようになりました。
let amount = null;
amount = amount ?? 1;
// => 1
amount = 0;
amount = amount ?? 1;
// => 0
[1] Undefined, MDN. (2021). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined (2021年6月4日にアクセス)。