JavaScript 中的 null 与 undefined:你真的搞懂它们的区别了吗?

在 JavaScript 的日常开发中,null 和 undefined 是我们几乎每天都会遇到的两个特殊值。它们都表示"没有值"或"空值",但它们的含义、来源和使用场景却大有不同。理解它们之间的区别,不仅能帮助我们写出更健壮的代码,也是 JavaScript 基础知识扎实的体现。

今天,我们就来深入剖析一下 null 和 undefined,彻底搞懂它们的异同。


1. 它们从哪里来?------ 源头大揭秘

理解一个事物,首先要看它的"出身"。

  • undefined 的来源:

    • 变量声明但未赋值: 这是最常见的来源。当你使用 var, let, 或 const 声明了一个变量,但没有给它赋值时,它的值就是 undefined。

      javascript 复制代码
      let name;
      console.log(name); // undefined
    • 函数没有返回值: 如果一个函数没有 return 语句,或者 return 后面没有跟任何值,那么该函数的返回值就是 undefined。

      javascript 复制代码
      function doNothing() {
          // 没有 return
      }
      console.log(doNothing()); // undefined
      
      function returnNothing() {
          return;
      }
      console.log(returnNothing()); // undefined
    • 对象中不存在的属性: 访问一个对象上不存在的属性时,会得到 undefined。

      ini 复制代码
      const person = { name: "Alice" };
      console.log(person.age); // undefined
    • 函数参数未传: 调用函数时,如果某个参数没有传入值,那么该参数的值就是 undefined。

      scss 复制代码
      function greet(name) {
          console.log("Hello, " + name);
      }
      greet(); // Hello, undefined
  • null 的来源:

    • null 是程序员显式赋值的结果。 它表示"一个空值"或"有意的空值"。null 不是 JavaScript 自动产生的,而是由开发者主动设置的。

      csharp 复制代码
      let emptyValue = null; // 明确表示这个变量现在是空的
    • 在 DOM 操作中,一些方法(如 document.getElementById())在找不到匹配的元素时会返回 null。这可以看作是 API 的设计,表示"没有找到"。

      ini 复制代码
      const nonExistentElement = document.getElementById("non-existent-id");
      console.log(nonExistentElement); // null

核心区别一: undefined 表示"系统层面的、默认的、未定义的状态 ",而 null 表示"程序层面的、有意的、空值"。


2. 类型检查:它们是什么类型?

我们可以使用 typeof 操作符来检查它们的类型。

javascript 复制代码
console.log(typeof undefined); // "undefined"
console.log(typeof null);      // "object"  ??? 

看到 typeof null 返回 "object",你是不是也一脸懵?这其实是 JavaScript 语言早期的一个著名 bug,一直被保留至今,因为它已经被大量代码所依赖,修复它会破坏现有的程序。

核心区别二: undefined 的类型是 "undefined",而 null 的类型在 typeof 检查下是 "object"(尽管这是一个历史遗留的错误)。

重要提示: 因为这个 bug,我们不能 用 typeof 来可靠地检查一个值是否为 null。如果你需要检查 null,应该直接与 null 进行比较。


3. 相等性比较:它们相等吗?

让我们来看看 == (抽象相等) 和 === (严格相等) 操作符下的表现。

javascript 复制代码
// 抽象相等 (==)
console.log(null == undefined); // true

// 严格相等 (===)
console.log(null === undefined); // false
  • == 比较: 在抽象相等比较中,null 和 undefined 被认为是相等的。这是 ECMAScript 规范中定义的特殊规则。
  • === 比较: 在严格相等比较中,null 和 undefined 不相等 ,因为它们是不同的类型(尽管 typeof null 有 bug,但内部类型是不同的)。

核心区别三: null == undefined 为 true,但 null === undefined 为 false。在实际开发中,强烈建议使用 === 来避免类型转换带来的意外行为。


4. 实际开发中的最佳实践

理解了区别,我们该如何在代码中正确使用它们呢?

  1. 不要主动给变量赋值 undefined:

    • 让 undefined 保持其"未定义"的语义。如果一个变量的初始值是空的,应该赋值为 null。

    • 反例:

      ini 复制代码
      let user = undefined; // 不推荐,这混淆了"未定义"和"空值"
    • 正例:

      csharp 复制代码
      let user = null; // 推荐,明确表示当前没有用户,但变量是"已定义"的
  2. null 用于表示"有意的空值":

    • 当你需要清空一个变量、对象或引用时,使用 null。

    • 例如,当用户登出时,清空用户信息:

      csharp 复制代码
      function logout() {
          currentUser = null; // 明确表示当前没有登录用户
      }
  3. 检查值是否存在:

    • 如果你不确定一个值是 null 还是 undefined,并且你想检查它是否"没有值",可以利用 null == undefined 为 true 的特性:

      javascript 复制代码
      if (value == null) {
          // value 是 null 或 undefined
          console.log("值不存在");
      }
    • 或者,更现代的方式是使用可选链 (?.) 和空值合并操作符 (??):

      ini 复制代码
      // 可选链,避免访问不存在属性时出错
      const age = user?.profile?.age; // 如果 user 或 profile 为 null/undefined, age 为 undefined
      
      // 空值合并,提供默认值
      const displayName = user.name ?? "Anonymous";
  4. 在函数参数中:

    • undefined 通常表示参数未被传入。
    • null 可以作为参数传入,表示"传入了一个空值"。
    • 函数内部可以根据需要区分处理。

总结

特性 undefined null
含义 "未定义",系统默认值 "空值",程序员有意设置
来源 变量声明未赋值、函数无返回、访问不存在属性、参数未传 程序员显式赋值、某些 API 返回(如 DOM 查找失败)
typeof 结果 "undefined" "object" (历史 bug)
== undefined true true
=== undefined true false
== null true true
=== null false true
最佳实践 避免主动赋值 用于表示"有意的空"

一句话总结: undefined 是 JavaScript 告诉你 "这里什么都没有定义",而 null 是你告诉 JavaScript"我明确地把这里设为空"。

掌握 null 和 undefined 的区别,是成为一名合格 JavaScript 开发者的基础。希望这篇文章能帮你彻底理清这两个容易混淆的概念!


互动时间: 你在开发中有没有遇到过因为 null 和 undefined 混淆而导致的 bug?欢迎在评论区分享你的经历!如果觉得这篇文章有帮助,别忘了点赞和收藏哦!

相关推荐
程序员大阳5 小时前
副队长JavaScript教程(67)-Ajax初识:背景、历史与核心概念
javascript·ajax·同步·异步·概念·背景·来是
程序员大阳6 小时前
副队长JavaScript教程(70)-Ajax同源策略与跨域
javascript·ajax·同源策略·跨越·corp
普通人66 小时前
Web端3D模型加载实战指南_Vue3_uni-app_HTML
前端·javascript·uni-app·html
志尊宝6 小时前
AI原生前端开发(042):AI辅助的路由设计与优化
javascript·react.js·ai-native
Dxy123931021617 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷17 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
椒哥19 小时前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
kyriewen20 小时前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员
OpsEye20 小时前
企业大模型压测,需要重点关注哪些指标?
javascript·ai编程
像我这样帅的人丶你还21 小时前
我html生成的doc文档为何在手机文档显示不了图片?
前端·javascript