与许多其他语言不同,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 年加入了可选链。
使用可选链运算符?.,可以确保只有当父级不是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或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。
编写一个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