0

0

JavaScript条件判断中的typeof null陷阱与安全实践

心靈之曲

心靈之曲

发布时间:2025-12-04 14:16:26

|

302人浏览过

|

来源于php中文网

原创

JavaScript条件判断中的typeof null陷阱与安全实践

本文深入探讨了javascript中`typeof null`返回`"object"`这一特性所导致的常见条件判断错误,以及如何避免因访问`null`属性而引发的`typeerror`。文章详细介绍了通过添加显式`null`检查来增强条件逻辑的健壮性,并提供了实际代码示例和现代javascript的解决方案,旨在帮助开发者编写更安全、可靠的代码。

在JavaScript开发中,我们经常需要根据变量的类型和值来执行不同的逻辑。一个常见的场景是,我们期望某个变量是一个对象,然后安全地访问其属性。然而,JavaScript中typeof运算符的一个历史遗留特性——typeof null的结果是"object"——常常会引入隐蔽的错误,导致即使在看似安全的类型检查之后,仍然会因为尝试访问null的属性而抛出TypeError。

理解typeof null的特性

在JavaScript中,null是一个原始值,表示“无值”或“空值”。然而,当你使用typeof运算符检查null时,你会得到一个令人困惑的结果:

console.log(typeof null); // 输出: "object"

这个行为是JavaScript语言设计上的一个历史错误,但由于兼容性原因,它一直保留至今。这意味着,如果你的代码中有一个条件判断,例如if (typeof someVar === "object"),那么当someVar的值是null时,这个条件也会被满足,从而允许代码块执行,并可能在后续尝试访问someVar的属性时引发TypeError: Cannot read properties of null。

常见的错误场景与TypeError分析

考虑以下代码片段,它尝试在确认loggerInfo是对象后,访问其section属性:

立即学习Java免费学习笔记(深入)”;

const getOfferingCourses = async () => {
    if (typeof loggerInfo === "object") { // 这里的条件可能包含 null
      if (typeof loggerInfo.section) { // 如果 loggerInfo 是 null,这里会报错
        // ... 后续逻辑 ...
      }
    }
  }

当loggerInfo变量的值为null时,外部的if (typeof loggerInfo === "object")条件会评估为true。代码会进入内部的if语句,然后尝试评估typeof loggerInfo.section。此时,由于loggerInfo是null,你不能访问null的任何属性(包括section),因此JavaScript运行时会抛出TypeError: Cannot read properties of null (reading 'section')。

错误堆通常会指向尝试访问null属性的那一行,例如:

Uncaught (in promise) TypeError: Cannot read properties of null (reading 'section')
    at getSchedule (s-schedule.js:43:1)
    // ... 其他堆栈信息 ...

这明确指示了问题出在试图读取null的section属性上。

解决方案:增强条件判断的健壮性

为了避免上述问题,我们需要在条件判断中显式地排除null值。

1. 显式检查null

在检查变量是否为对象时,务必同时检查它是否不为null。

修正第一个if条件:

将原始的:

if (typeof loggerInfo === "object")

修改为:

if (typeof loggerInfo === "object" && loggerInfo !== null)

这样,只有当loggerInfo确实是一个非null的对象时,代码才会进入内部逻辑,从而避免了对null属性的访问。

极简智能王
极简智能王

极简智能- 智能聊天AI绘画,还可以创作、编写、翻译、写代码等多种功能,满足用户生活和工作的多方面需求

下载

2. 安全地访问嵌套属性

即使在确认了外部对象非null之后,内部的嵌套属性也可能不存在(即为undefined)。在访问这些属性之前,也应该进行检查。

修正第二个if条件:

原始的条件if (typeof loggerInfo.section)实际上是不完整的,它只会检查typeof loggerInfo.section的结果是否是一个真值(例如,"string"、"number"等)。如果loggerInfo.section是undefined,typeof undefined会返回"undefined",这是一个字符串,在布尔上下文中会被评估为true。这可能不是你期望的行为。

你可以选择以下两种更明确的方式:

  • 检查属性是否不是undefined:

    if (typeof loggerInfo.section !== "undefined")

    这种方法确保section属性确实存在。

  • 利用属性的真值性(Truthy)检查:

    if (loggerInfo.section)

    这种方法更简洁,它会检查loggerInfo.section是否是一个真值(非null、非undefined、非0、非空字符串""、非false)。这通常是处理可选属性的有效方式,但需要注意它会将0、空字符串和false也视为“不存在”或“不满足条件”。根据你的业务逻辑选择最合适的。

整合后的代码示例

将上述修正应用到原始函数中,得到更健壮的代码:

const getOfferingCourses = async () => {
    // 修正1:确保 loggerInfo 是一个非 null 的对象
    if (typeof loggerInfo === "object" && loggerInfo !== null) {
      // 修正2:确保 loggerInfo.section 存在且不是 undefined
      // 或者根据业务逻辑使用 if (loggerInfo.section) 进行真值检查
      if (typeof loggerInfo.section !== "undefined") { 
        const formdata = new FormData();
        formdata.append("getOfferingCourse", loggerInfo.section);

        try {
            let dep = await fetch(baseUrl + "enroll.php", {
              method: "POST",
              headers: {
                Accept: "application/json",
              },
              body: formdata,
            });
            let depa = await dep.json();

            // 确保 depa 存在且其 status 属性为 "success"
            if (depa && typeof depa === "object" && depa.status === "success") {
              setOffeing(depa.data.offering);
              setOffCourses(depa.data.courses);
            }
        } catch (error) {
            console.error("获取课程数据失败:", error);
            // 处理 fetch 或 JSON 解析错误
        }
      }
    }
  }

注意事项:

  • 在实际开发中,fetch操作最好包裹在try...catch块中,以优雅地处理网络错误或JSON解析错误。
  • 对于depa变量,也需要进行类似的检查,以确保它是一个有效的对象,并且可以安全地访问其status和data属性。

现代JavaScript的解决方案:可选链(Optional Chaining)

对于处理可能为null或undefined的嵌套属性访问,现代JavaScript提供了一个更简洁、更优雅的语法:可选链(Optional Chaining ?.)。

使用可选链,你可以这样重写对loggerInfo.section的访问:

const getOfferingCourses = async () => {
    // 使用可选链简化对 loggerInfo.section 的访问
    // 只有当 loggerInfo 存在且非 null,并且 loggerInfo.section 存在且非 null/undefined 时,才会使用其值
    const sectionValue = loggerInfo?.section;

    if (sectionValue) { // 检查 sectionValue 是否为真值
      const formdata = new FormData();
      formdata.append("getOfferingCourse", sectionValue);

      try {
          let dep = await fetch(baseUrl + "enroll.php", {
            method: "POST",
            headers: {
              Accept: "application/json",
            },
            body: formdata,
          });
          let depa = await dep.json();

          // 再次使用可选链和逻辑判断
          if (depa?.status === "success") {
            setOffeing(depa.data?.offering); // 也可以对 data 属性使用可选链
            setOffCourses(depa.data?.courses);
          }
      } catch (error) {
          console.error("获取课程数据失败:", error);
      }
    }
  }

可选链极大地简化了深层嵌套属性的空值检查,使代码更加清晰和易读。它会在遇到null或undefined时短路,表达式直接返回undefined而不是抛出TypeError。

总结

JavaScript中typeof null === "object"是一个需要特别注意的语言特性。为了编写健壮且无错误的条件逻辑,当使用typeof variable === "object"进行类型检查时,务必同时添加&& variable !== null的显式null检查。此外,对于嵌套属性的访问,应始终进行安全检查,无论是通过typeof property !== "undefined"、真值性检查if (property),还是利用现代JavaScript提供的可选链?.操作符。采用这些实践将有效避免TypeError: Cannot read properties of null等常见运行时错误,提升代码的稳定性和可靠性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

453

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

546

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

331

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

82

2025.09.10

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

970

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

252

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1049

2024.03.01

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1561

2023.10.24

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.1万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号