前言
JavaScript 作为一门动态语言,允许开发者写出非常简洁又灵活的代码。不过,这也带来了一个问题:在访问对象的深层属性时,经常会遇到 null 或 undefined 的情况,导致程序报错。ES2020 引入了两个非常实用的操作符来解决这个问题,它们分别是 空值合并运算符(??)和 可选链操作符(?.)。
今天我将带你轻松搞定这两个“黑科技”——用小白也能看懂的方式为你讲解,⚡代码更简单、报错更少!✨
一、空值合并运算符(??
)
1. 它是什么?
空值合并运算符(??
)其实就是一种“给空值提供备胎”的方式。在写代码的时候,如果你发现某个变量可能是 null
或 undefined
,那么就可以用 ??
来给它一个“备用值”。也就是说,当变量没值(也就是 null
或 undefined
)时,用右边的备用值来代替。
2. 它怎么用?
举个例子,你有一个变量 username
,但它有可能是空的(比如用户没填写名字)。为了不让页面上出现“空空如也”的情况,你想显示一个默认的名字 "Guest"
。传统写法是这样的:
let username = firstName || "Guest";
这是什么意思呢?如果 firstName
是“假值”,那就用 "Guest"
。
⚠️ 问题来了:空字符串 ""
、0
、false
这些也是“假值”,但它们可能是你需要的值啊!用 ||
的话,连这些值也会被替换掉,不合适。
于是我们引入 ??
:
let username = firstName ?? "Guest";
现在,只有当 firstName
是 null
或 undefined
的时候,username
才会被赋值为 "Guest"
。如果 firstName
是空字符串 ""
、0
,它们还是会保留。
3. 举个简单例子
- 例子1:变量是
null
let firstName = null;
let username = firstName ?? "Guest";
console.log(username); // 输出 "Guest"
因为 firstName
是 null
,所以 username
被赋值为 "Guest"
。
- 例子2:变量是空字符串
let firstName = "";
let username = firstName ?? "Guest";
console.log(username); // 输出 ""
在这里,firstName
是空字符串 ""
,但由于它不是 null
或 undefined
,所以它会被保留。
这样用 ??
就避免了 ||
带来的误伤:保留了空字符串和 0,而不是直接用默认值覆盖它们。
二、可选链操作符(?.
)
1. 它是什么?
可选链操作符(?.
)可以帮助你在访问对象的深层属性时,避免程序因为找不到属性而报错。
想象一下,如果你想从一个嵌套的对象里访问某个属性,比如:
let firstName = message.body.user.firstName;
问题是,如果 message
或 message.body
是 null
或 undefined
,你的代码就会直接报错!🚨
2. 它怎么用?
用 ?.
你可以轻松判断对象的每一级是不是存在。如果某一级不存在,代码不会崩溃,而是直接返回 undefined
。像这样:
let firstName = message?.body?.user?.firstName;
如果 message
或 message.body
不存在,firstName
就会是 undefined
,但不会报错。
3. 举个简单例子
- 例子1:对象缺失某个属性
let message = {};
let firstName = message?.body?.user?.firstName ?? "Guest";
console.log(firstName); // 输出 "Guest"
在这个例子中,message
没有 body
属性,但你依然可以访问 firstName
而不报错。结果是 firstName
被赋值为 "Guest"
。
- 例子2:对象属性存在
let message = { body: { user: { firstName: "John" } } };
let firstName = message?.body?.user?.firstName;
console.log(firstName); // 输出 "John"
这里,message
对象里的 body
和 user
都存在,因此 firstName
正常输出 "John"
。
三、空值合并与可选链的结合——双剑合璧
有时候,我们会把 ??
和 ?.
一起使用来做链式属性访问和空值处理。比如:
let animationDuration = response.settings?.animationDuration ?? 300;
这个代码是什么意思呢?它会首先检查 response.settings
和 response.settings.animationDuration
是否存在。如果它们都不存在,代码会自动返回 300
作为默认值。简洁又安全!😎
四、注意事项——优先级问题
用 ??
和 ?.
非常方便,但在一些情况下需要注意优先级问题。比如,如果你同时用到 &&
或 ||
,你需要加括号来明确表达式的优先级,否则会报错:
let username = (firstName || lastName) ?? "Guest";
这里的括号确保 firstName || lastName
先执行,再用 ??
处理最终结果。
总结:
- 空值合并运算符
??
:当变量是null
或undefined
时,提供默认值,避免||
覆盖0
、""
等合法值。 - 可选链操作符
?.
:访问深层嵌套对象属性时,不再因为null
或undefined
报错,返回undefined
而不是崩溃。
通过这两个操作符,你可以显著减少代码中的防御性判断,简化逻辑,提高代码的可读性和健壮性。快试试看吧!