蓝心石 發表於 2026-1-8 11:47:01

浅析JavaScript中如何正确判断null和undefined

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、为什么需要判断空值?</a></li><li><a href="#_label1">二、先搞懂:null 和 undefined 有啥区别?</a></li><li><a href="#_label2">三、判断方法</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">方法一:显式比较(最保险)</a></li><li><a href="#_lab2_2_1">方法二:非严格相等(最常用)</a></li><li><a href="#_lab2_2_2">方法三:逻辑非操作符</a></li><li><a href="#_lab2_2_3">方法四:typeof 关键字(安全的写法)</a></li><li><a href="#_lab2_2_4">方法五:空值合并操作符(现代写法)</a></li><li><a href="#_lab2_2_5">方法六:可选链操作符(对象属性专用)</a></li></ul><li><a href="#_label3">四、实际开发中的建议</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_6">场景1:简单的空值检查</a></li><li><a href="#_lab2_3_7">场景2:需要区分null和undefined</a></li><li><a href="#_lab2_3_8">场景3:处理对象属性</a></li><li><a href="#_lab2_3_9">场景4:函数参数默认值</a></li></ul><li><a href="#_label4">五、总结</a></li><ul class="second_class_ul"></ul></ul></div><p>相信写前端开发的朋友对下面这种报错应该很熟悉:</p>
<blockquote><p>Cannot read properties of undefined</p></blockquote>
<p>有一次我加班处理问题,也是因为这一个bug。</p>
<p>后来才发现,原来是一个接口返回的数据里,某个字段有时候是null导致的,而我没有做判断就直接使用了。</p>
<p class="maodian"><a name="_label0"></a></p><h2>一、为什么需要判断空值?</h2>
<p>举例如下:</p>
<div class="jb51code"><pre class="brush:js;">// 场景1:用户没填姓名
const userName = undefined;
console.log(userName.length); // 报错!Cannot read properties of undefined

// 场景2:接口返回空数据
const apiResponse = null;
console.log(apiResponse.data); // 报错!Cannot read properties of null
</pre></div>
<p>所以,空值判断是保证代码健壮性的重要环节。</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、先搞懂:null 和 undefined 有啥区别?</h2>
<p>虽然它们都表示空,但含义不同:</p>
<p><code>undefined</code>:变量被声明了,但还没赋值。</p>
<div class="jb51code"><pre class="brush:js;">let name;
console.log(name); // undefined
</pre></div>
<p><code>null</code>:程序员主动赋值为空,表示我明确知道这里没有值。</p>
<div class="jb51code"><pre class="brush:js;">let user = null; // 表示“用户不存在”
</pre></div>
<p>所以,当我们说判断变量是否为空,通常是指:它是不是 <code>null</code> 或 <code>undefined</code>。</p>
<p class="maodian"><a name="_label2"></a></p><h2>三、判断方法</h2>
<p>以下介绍了比较常用的几种判断方案。</p>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>方法一:显式比较(最保险)</h3>
<div class="jb51code"><pre class="brush:js;">if (variable === null || variable === undefined) {
console.log('变量为空');
}
</pre></div>
<p><strong>适用场景</strong>:</p>
<ul><li>需要明确区分null和undefined时</li><li>团队代码规范要求严格相等判断</li><li>对代码可读性要求高的项目</li></ul>
<p><strong>案例</strong>:</p>
<div class="jb51code"><pre class="brush:js;">function getUserProfile(user) {
if (user === null || user === undefined) {
    return '用户不存在';
}
return `欢迎,${user.name}`;
}
</pre></div>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>方法二:非严格相等(最常用)</h3>
<div class="jb51code"><pre class="brush:js;">if (variable == null) {
console.log('变量为空');
}
</pre></div>
<p>这里有个<strong>重要知识点</strong>:<code>== null</code> 实际上等价于 <code>=== null || === undefined</code>,这是JavaScript的语言特性。</p>
<p><strong>为什么推荐这个写法?</strong></p>
<ul><li>代码简洁,少写很多字符</li><li>性能优秀,现代JS引擎都做了优化</li><li>意图明确,专业开发者一看就懂</li></ul>
<p class="maodian"><a name="_lab2_2_2"></a></p><h3>方法三:逻辑非操作符</h3>
<div class="jb51code"><pre class="brush:js;">if (!variable) {
console.log('变量为falsy值');
}
</pre></div>
<p><strong>注意!</strong> 这个方法容易造成其它的误伤:</p>
<div class="jb51code"><pre class="brush:js;">// 这些值都会被判断为"空"
!false      // true
!0         // true
!""      // true
!NaN       // true

// 实际开发中的坑
const count = 0;
if (!count) {
console.log('计数为0'); // 这里会执行,但可能不是我们想要的
}
</pre></div>
<p class="maodian"><a name="_lab2_2_3"></a></p><h3>方法四:typeof 关键字(安全的写法)</h3>
<div class="jb51code"><pre class="brush:js;">if (typeof variable === 'undefined' || variable === null) {
console.log('变量是空的!');
}
</pre></div>
<p>安全在哪?</p>
<div class="jb51code"><pre class="brush:js;">// 如果变量根本没声明,前两种方法会报错
if (notDeclaredVariable == null) { // 报错!ReferenceError
}

if (typeof notDeclaredVariable === 'undefined') { // 正常运行!
console.log('变量未定义');
}
</pre></div>
<p>这种写法主要用于检查一个变量是否被声明过,但对于普通函数参数或已声明变量,没必要这么复杂。</p>
<p>适用于不确定变量是否声明的场景。</p>
<p class="maodian"><a name="_lab2_2_4"></a></p><h3>方法五:空值合并操作符(现代写法)</h3>
<p>这是ES2020的新特性,用起来特别顺手:</p>
<div class="jb51code"><pre class="brush:js;">// 传统写法
const name = username ? username : '匿名用户';

// 现代写法
const name = username ?? '匿名用户';
</pre></div>
<p><strong>优势</strong>:只对 <code>null</code> 和 <code>undefined</code> 生效,不会误判0、false等其他值。</p>
<p class="maodian"><a name="_lab2_2_5"></a></p><h3>方法六:可选链操作符(对象属性专用)</h3>
<p>处理嵌套对象时,这个功能简直是救命稻草:</p>
<div class="jb51code"><pre class="brush:js;">// 以前的痛苦写法
const street = user &amp;&amp; user.address &amp;&amp; user.address.street;

// 现在的优雅写法
const street = user?.address?.street;
</pre></div>
<p>结合空值合并,写法更加安全:</p>
<div class="jb51code"><pre class="brush:js;">const street = user?.address?.street ?? '地址未知';
</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>四、实际开发中的建议</h2>
<p class="maodian"><a name="_lab2_3_6"></a></p><h3>场景1:简单的空值检查</h3>
<div class="jb51code"><pre class="brush:js;">// 推荐
if (value == null) {
// 处理空值
}

// 或者
const safeValue = value ?? defaultValue;
</pre></div>
<p class="maodian"><a name="_lab2_3_7"></a></p><h3>场景2:需要区分null和undefined</h3>
<div class="jb51code"><pre class="brush:js;">if (value === null) {
console.log('明确设置为空');
}

if (value === undefined) {
console.log('未定义');
}
</pre></div>
<p class="maodian"><a name="_lab2_3_8"></a></p><h3>场景3:处理对象属性</h3>
<div class="jb51code"><pre class="brush:js;">// 安全访问深层属性
const phone = order?.customer?.contact?.phone ?? '未填写';
</pre></div>
<p class="maodian"><a name="_lab2_3_9"></a></p><h3>场景4:函数参数默认值</h3>
<div class="jb51code"><pre class="brush:js;">function createUser(name, age = 18) {
// age参数只在undefined时使用默认值
return { name, age };
}
</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>五、总结</h2>
<p>虽然现代JavaScript引擎优化得很好,但了解原理还是有帮助的:</p>
<ul><li><code>== null</code> 和显式比较性能相当</li><li><code>typeof</code> 检查稍慢,但能安全检测未声明变量</li><li>可选链操作符在现代浏览器中性能优秀</li></ul>
<table><thead><tr><th>场景</th><th>推荐写法</th><th>原因</th></tr></thead><tbody><tr><td>一般空值检查</td><td>value == null</td><td>简洁高效</td></tr><tr><td>需要明确意图</td><td>value === undefined</td><td>可读性强</td></tr><tr><td>设置默认值</td><td>value ?? defaultValue</td><td>安全准确</td></tr><tr><td>对象属性访问</td><td>obj?.prop</td><td>避免报错</td></tr><tr><td>函数参数</td><td>参数默认值</td><td>语言特性</td></tr></tbody></table>
<p>没有绝对最好的方法,只有最适合当前场景的选择。根据你的具体需求和团队规范来决策吧!</p>
頁: [1]
查看完整版本: 浅析JavaScript中如何正确判断null和undefined