到了这一小节,我终于可以说“最后”了。在我看来,这两个功能对于 JavaScript 语言来说是非常有用的。作为一个来自 C# 世界的人,可以说我经常使用它们。
在写这篇文章的时候,这些还没有得到完全的支持。因此,对于以这种方式编写的代码,你需要使用 Babel 进行编译。你可以在自判断链接这里以及在空合并这里查阅。
自判断链接允许我们在没有显式检查中间节点是否存在的时候处理树形结构,空合并可以确保节点不存在时会有一个默认值,配合自判断链接使用会有不错的效果。
让我们用一些例子来支撑上面的结论。一开始,我们还是用以前的老方法:
const car = { model: 'Fiesta', manufacturer: { name: 'Ford', address: { street: 'Some Street Name', number: '5555', state: 'USA' } } } // 获取汽车模型 const model = car && car.model || 'default model'; // 获取厂商地址 const street = car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.street || 'default street'; // 请求一个不存在的属性 const phoneNumber = car && car.manufacturer && car.manufacturer.address && car.manufacturer.phoneNumber; console.log(model) // 输出 'Fiesta' console.log(street) // 输出 'Some Street Name' console.log(phoneNumber) // 输出 undefined
因此,如果我们想要知道厂商是否来自 USA 并将结果打印,那么代码是这样的:
const checkCarManufacturerState = () => { if(car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.state === 'USA') { console.log('Is from USA'); } } checkCarManufacturerState() // 输出 'Is from USA'
我无需再赘述如果对象结构更加复杂的话,代码会多么混乱了。许多库,例如 lodash,有自己的函数作为替代方案。不过这不是我们想要的,我们想要的是在原生 js 中也能做同样的事。我们来看一下新的方法:
// 获取汽车模型 const model = car?.model ?? 'default model'; // 获取厂商地址 const street = car?.manufacturer?.address?.street ?? 'default street'; // 检查汽车厂商是否来自 USA const checkCarManufacturerState = () => { if(car?.manufacturer?.address?.state === 'USA') { console.log('Is from USA'); } }
这看起来更加漂亮和简洁,对我来说,非常符合逻辑。如果你想知道为什么应该使用 ?? 而不是 || ,只需想一想什么值可以当做 true 或者 false,你将可能有意想不到的输出。
顺便说句题外话。自判断链接同样支持 DOM API,这非常酷,意味着你可以这么做:
const value = document.querySelector('input#user-name')?.value;