BlueSkyUSC 2020-09-27
JavaScript以众多技巧出名,了解JavaScript的所有技巧几乎不可能。最近在浏览JavaScript的相关文件,阅读相关话题时我又发现了一个从没见过的功能点。我大概不是最后一个学到这个技巧的人,所以我想与各位分享。 它完全改变了我访问嵌套对象的方式!希望它能够帮助到你们。
技巧 这个技巧就叫做可选链。它实际上是一个操作符,写法是 ?.。根据Mozilla网站文件,可选链操作符的功能是:允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。 简而言之,可选链操作符大大简化了对嵌套对象的访问。直接看这个例子,帮助你更好地理解可选链操作符的作用。 假如有对象“房子(house)”如下:
const house = { price: 1000000, currency: USD , address: { city: New York , street: Main street , postal_code: 1234 AB , state: { name: New York , abbreviation: N.Y. } }, owner: { name: "John Doe" }}
通常要按照如下方式访问对象属性:
const currency = house.currencyconst price = house.priceconst owner = house.owner.name
这是读取对象值的基础。如果房子没有主人呢?我们将无法读取不存在的命名属性,而最后一行代码会引起错误。要想弥补这一点,可以这样做:
const owner = house.owner ? house.owner.name : null
高手们可以使用空值合并运算符:
const owner = house.owner.name ?? null
这串代码的问题在于,即使房子这个对象没有主人,它也不会停止运行。看看下面这个例子:
const house = { price: 1000000, currency: USD , address: { city: New York , street: Main street , postal_code: 1234 AB , state: { name: New York , abbreviation: N.Y. } }, owner: null}
使用空值合并运算符会造成错误,因为它不能读取属性中为空的命名(name)。使用三元运算符可以运行第一个例子。但如果要探索的属性是多层嵌套的,还需要挨个检查是否存在,那么代码会很冗长,也无法读取。 比如,检查所在州:
const state = house.address &&house.address.state ? house.address.state.name : null
如你所见,这行代码变得非常长,无法读取。这时可选链操作符就派上了用场。有了它就不再需要检查某个属性是否存在,从而保持代码简明易懂。如果属性不存在则会返回“undefined”。操作符实际看起来是这样的:
const city = house?.address?.city // "New York"const nonExisting = house?.roof?.material // Undefinedconst houseNumber = house?.address?.number // Undefinedconst state = house?.address?.state?.abbreviation // "N.Y."
是不是一下子就变得很简洁明了!
图源:unsplash
例一尝试探索“address”属性下“city”属性的值。因为这个属性存在,“城市”属性将会被返回,和使用house.address.city来获取值一样的。 例二尝试获得房顶(roof)建材的信息。然而“house”对象下没有“roof”这一属性,因此返回的是“undefined”,“houseNumber”属性也是同理。虽然“house”对象有“address”属性,这个属性却不包含“number”属性——也就是这里返回了“undefined”的原因。 你也可以使用可选链操作符来动态查询属性,这时需要使用括号:
const someProperty = obj?.[ property- + propertyName]
也可以与空值合并运算符一起使用。如果要为一个变量设定默认值,例证如下:
const ownerName = house?.owner?.name ?? "Unknownowner"
函数
目前只是将可选链操作符与对象结合。但它也可以与函数结合使用。可以用来调取不存在的方法,就像这样:
const result = someObject.customMethod?.();
适配