他の多くのプログラミング言語とは異なり、JavaScriptには、意味のある値が存在しないことを表すものが2つあります。
nullとundefinedです。
nullプリミティブ値のnullは、どの型の変数に対しても、意図的な「空の値」として使われます。
let name = null;
// name is intentionally set to "empty" because it is not
// available
変数がnullかどうかは、厳密等価演算子===を使うと確認できます。
let name = null;
name === null;
// => true
undefined値を代入していない変数は、
undefinedという型になります。1
つまり、nullが空の値(ただし値ではあります)を表すのに対して、undefinedは値がまったく存在しないことを表します。🤯
undefinedは、さまざまな場面で登場します。
undefinedになります。undefinedが返ります。undefinedになります。undefinedになります。let name;
console.log(name);
// => undefined
変数がundefinedかどうかは、厳密等価演算子===を使うと確認できます。
let name;
name === undefined;
// => true
オブジェクトの入れ子になった値を取得しようとしたとき、親のキーが存在しないと、JavaScriptはエラーを投げます。
これを手軽に避けるために、2020年にオプショナルチェイニングが言語仕様に追加されました。
オプショナルチェイニング演算子?.を使うと、親がnullやundefinedでない場合にだけ、JavaScriptが入れ子のキーにアクセスしようとするようにできます。
そうでなければ、undefinedが返されます。
const obj = {
address: {
street: 'Trincomalee Highway',
city: 'Batticaloa',
},
};
obj.address.zipCode;
// => undefined
obj.residence.street;
// => TypeError: Cannot read property 'street' of undefined
obj.residence?.street;
// => undefined
変数がnullやundefinedの場合にだけ、デフォルト値を適用したいという場面があります。
これに対応するために、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日閲覧).
遊園地のITシステムの一部を提供し、維持する仕事を担当します。 特に、来園者とチケットを管理するプログラムを担当します。
まず、システムに新しい来園者を登録します。 次に、チケットを無効にする関数を作成します。 タスク3と4では、偽造を防ぐのに役立つチケット追跡システムに取り組みます。 最後に、新しい法的要件に合わせてシステムを適応させる手助けをします。
来園者が初めて遊園地に来るときは、ターミナルで名前と年齢を入力し、利用規約に同意して登録する必要があります。
もちろん、チケットも購入する必要があります。
各チケットにはH32AZ123のような識別子があります。
3つの引数を取る関数createVisitorを書きましょう。
関数は、この情報を保持するオブジェクトを返す必要があります。
オブジェクトのキーはname、age、ticketIdとします。
createVisitor('Verena Nardi', 45, 'H32AZ123');
// => { name: 'Verena Nardi', age: 45, ticketId: 'H32AZ123' }
来園者が遊園地を去るとき、そのチケットは無効になります。 また来る場合は、新しいチケットを購入する必要があります。 常連の来園者の手間を省くため、登録は一度だけでよく、来園者の情報は次回以降の来園のために保持されます。
つまり、来園者が遊園地を去るときに無効になるのはチケットだけで、来園者オブジェクトの残りの部分はそのまま残ります。
来園者オブジェクトを受け取り、チケットの識別子をnullに設定して、そのあとでオブジェクトを返す関数revokeTicketを実装しましょう。
const visitor = {
name: 'Verena Nardi',
age: 45,
ticketId: 'H32AZ123',
};
revokeTicket(visitor);
// => { name: 'Verena Nardi', age: 45, ticketId: null }
偽造を防ぐため、チケットの識別子は一意です。 チケットが印刷されると、追跡できるように、その識別子がシステム内のオブジェクトのキーとして追加されます。
チケットが来園者に販売される前は、チケット追跡オブジェクトにnullという値で保存されます。
来園者に販売されると、その来園者の名前が値として代入されます。
従業員がチケットの有効性に疑問を感じたときは、システムでチケットの状態を確認する必要があります。
追跡オブジェクトとチケットの識別子を引数として受け取る関数ticketStatusを実装しましょう。
この関数は、次のいずれかの結果を返します。
'unknown ticket id'
'not sold'
'sold to {name}'。ここで{name}は来園者の名前です。const tickets = {
'0H2AZ123': null,
'23LA9T41': 'Verena Nardi',
};
ticketStatus(tickets, 'RE90VAW7');
// => 'unknown ticket id'
ticketStatus(tickets, '0H2AZ123');
// => 'not sold'
ticketStatus(tickets, '23LA9T41');
// => 'sold to Verena Nardi'
しばらくすると、従業員から、チケットの状態をひと目でわかりやすくしてほしいというフィードバックが届きます。 従業員は、来園者の名前か、チケットが無効であるかのどちらかだけを知りたいと思っています。
タスク3のticketStatusと同じ引数を取る関数simpleTicketStatusを書きましょう。
この関数は、2つの結果のうちのどちらか一方だけを返します。
'invalid ticket !!!'
const tickets = {
'0H2AZ123': null,
'23LA9T41': 'Verena Nardi',
};
simpleTicketStatus(tickets, '23LA9T41');
// => 'Verena Nardi'
simpleTicketStatus(tickets, '0H2AZ123');
// => 'invalid ticket !!!'
simpleTicketStatus(tickets, 'RE90VAW7');
// => 'invalid ticket !!!'
新しい法的要件により、新しく作成される来園者オブジェクトには、ユーザーが同意した「一般利用規約」(GTC)に関する詳細情報も含まれるようになりました。 新しい来園者オブジェクトの例を以下に示します。
遊園地のレジ係は、来園者が新しいバージョンのGTCに署名する必要があるかどうかを確認する必要があります。
そのために、来園者オブジェクトを引数として受け取り、GTCのバージョンが利用可能であればそれを返す関数gtcVersionを実装しましょう。
バージョン情報が利用できない場合は、何も返しません。
const visitorNew = {
name: 'Verena Nardi',
age: 45,
ticketId: 'H32AZ123',
gtc: {
signed: true,
version: '2.1',
},
};
gtcVersion(visitorNew);
// => '2.1'
const visitorOld = {
name: 'Verena Nardi',
age: 45,
ticketId: 'H32AZ123',
};
gtcVersion(visitorOld);
// => undefined
Exercismに登録すれば、37個のコンセプト159個の演習、そして本物の人間によるメンタリングとともに、JavaScriptを学んでマスターできます。すべて無料です。