與許多其他語言不同,JavaScript 裡有兩個不同的實體,用來表示(有意義的)值不存在。
它們分別是null與undefined。
原始值null用於刻意表示任何型別變數的「空值」。
let name = null;
// name is intentionally set to "empty" because it is not
// available
你可以用嚴格相等運算子===來檢查一個變數是否為null。
let name = null;
name === null;
// => true
尚未被指定值的變數,其型別為
undefined。1
這表示null代表的是一個空值(但仍然是一個值),而undefined則代表完全沒有值。🤯
undefined會出現在不同的情境中。
undefined。undefined。undefined。undefined,除非這個引數有預設值。let name;
console.log(name);
// => undefined
你可以使用嚴格相等運算子===來檢查一個變數是否為undefined。
let name;
name === undefined;
// => true
如果你想取得物件中巢狀的值,但父層的鍵不存在,JavaScript 會拋出錯誤。
為了輕鬆避免這種情況,選擇性鏈結在 2020 年被加入語言規格中。
使用選擇性鏈結運算子?.,你可以確保 JavaScript 只在父層不是null或undefined時,才嘗試存取巢狀的鍵。
否則,它會回傳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或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 日)。
你的工作是提供並維護遊樂園資訊系統的部分功能。特別是,你負責管理訪客與票券的程式。
首先,你會在系統中建立一位新訪客。接著,你會提供一個用來註銷票券的函式。在第 3 和第 4 項任務中,你會處理票券追蹤系統,它能協助防止偽造。最後,你會協助讓系統配合新的法律要求。
訪客第一次來到遊樂園時,需要在終端機輸入姓名與年齡,並同意條款與細則,才能完成註冊。當然,他們還需要買一張票券。每張票券都有一個像H32AZ123這樣的識別碼。
撰寫一個createVisitor函式,它接受三個引數。
這個函式應回傳一個包含上述資訊的物件。物件中的鍵應命名為name、age和ticketId。
createVisitor('Verena Nardi', 45, 'H32AZ123');
// => { name: 'Verena Nardi', age: 45, ticketId: 'H32AZ123' }
當人們離開遊樂園時,他們的票券會被註銷。如果他們再回來,就需要買一張新的票券。為了節省常客的時間,他們只需要註冊一次,訪客資訊會保留到之後的來訪。
這表示當訪客離開園區時,只有他們的票券應該被註銷,而訪客物件的其餘部分應保持不變。實作revokeTicket函式,它接受一個訪客物件,將票券識別碼設為null,然後回傳該物件。
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'
過了一陣子,你收到員工的回饋,他們希望票券狀態能更容易一眼看懂。他們只想看到訪客姓名,或是票券無效的提示。
撰寫simpleTicketStatus函式,它接受與第 3 項任務中ticketStatus相同的引數。這個函式只會回傳兩種不同結果的其中一種。
'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。為此,實作gtcVersion函式,它接受一個訪客物件作為引數,並在 GTC 版本資訊存在時回傳該版本。如果沒有版本資訊,則不應回傳任何東西。
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