ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

JavaScript 值的比较:7 道练习题精解相等性、类型转换与 null/undefined 陷阱

JavaScript 值的比较:7 道练习题精解相等性、类型转换与 null/undefined 陷阱 文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载在 JavaScript 中值的比较远比表面看起来复杂字符串之间按词典序逐字符比较、不同类型的值会被先转成数字、null与undefined拥有独立的特殊规则而与的行为又截然不同。本文以《现代 JavaScript 教程》中值的比较章节的 7 道经典练习题task.md及其官方解答solution.md为核心骨架逐题拆解结果背后的比较规则并结合主章节 article.md 与类型转换章节 的源码级原理帮助你彻底吃透相等性检查与类型转换从此远离JavaScript 陷阱。题目总览一组看似简单却暗藏玄机的问题这组练习题来自 1-comparison-questions 目录题目要求判断以下 7 个表达式的执行结果5 4 apple pineapple 2 12 undefined null undefined null null \n0\n null \n0\n先不要看答案凭直觉写出你的判断。如果你对其中任何一题犹豫甚至觉得结果反直觉那么这篇文章正是为你准备的。官方标准答案如下5 4 → true apple pineapple → false 2 12 → true undefined null → true undefined null → false null \n0\n → false null \n0\n → false接下来我们先快速建立比较规则的知识底座再逐题推导确保每一行结果都有明确的规则依据。先建立知识底座JavaScript 的比较规则速览要读懂这 7 道题需要先掌握 article.md 中阐述的四条核心规则。规则一比较结果永远是布尔值所有比较运算符、、、、、!等均返回布尔类型true—— 表示是正确真false—— 表示否错误非真。alert( 2 1 ); // true正确 alert( 2 1 ); // false错误 alert( 2 ! 1 ); // true正确和其他类型的值一样比较结果可以赋值给任意变量let result 5 4; // 把比较的结果赋值给 result alert( result ); // true规则二字符串按词典序逐字符比较在比较字符串大小时JavaScript 使用字典dictionary或词典lexicographical顺序判定——即按字符逐个比较。算法非常简单首先比较两个字符串的首位字符大小如果一方字符较大或较小则该字符串大于或小于另一个字符串算法结束否则如果两个字符串的首位字符相等则继续取出两个字符串各自的后一位字符进行比较重复上述步骤直到比较完成某字符串的所有字符为止如果两个字符串的字符同时用完则判定它们相等否则未结束还有未比较字符的字符串更大。例如alert( Z A ); // true alert( Glow Glee ); // true alert( Bee Be ); // trueGlow与Glee的比较过程为G和G相等 →l和l相等 →o比e大算法停止第一个字符串更大。需要注意的是这不是真正的字典顺序而是Unicode 编码顺序比较对大小写敏感大写的A不等于小写的a且小写的a更大——因为在 Unicode 编码表中小写字母的字符索引值更大。规则三不同类型比较时先转数字当对不同类型的值进行比较时JavaScript 会首先将它们转化为数字number再判定大小alert( 2 1 ); // true字符串 2 被转化为数字 2 alert( 01 1 ); // true字符串 01 被转化为数字 1对于布尔类型true转化为1false转化为0alert( true 1 ); // true alert( false 0 ); // true数字型转换的完整规则可以在类型转换章节中找到undefined变为NaNnull变为0true/false变为1/0字符串则去掉首尾空白空格、换行符\n、制表符\t等后读取数字空字符串变为0读取失败返回NaN。这里有一个有趣的现象值得警惕两个值直接比较可能相等但各自转为布尔值却可能相反。例如a 0时Boolean(a)为false而b 0时Boolean(b)为true但a b的结果却是true——因为先做数字转换0变为0而Boolean转换遵循的是另一套空值规则。规则四严格相等不做类型转换普通的相等性检查无法区分0和falsealert( 0 false ); // true alert( false ); // true原因在于会把两侧的值先转成数字空字符串和false都变为0。严格相等运算符在进行比较时不会做任何类型转换——如果a和b属于不同的数据类型a b会立刻返回falsealert( 0 false ); // false因为被比较值的数据类型不同与!对应的严格不相等写作!。虽然写起来稍长但它能清楚显示代码意图降低犯错概率。规则五null与undefined的特殊地位null和undefined在比较中的行为需要单独记忆严格相等下null undefined为false因为它们属于不同的类型非严格相等下存在特殊规则判定null undefined为true——它俩就像一对恋人仅仅等于对方而不等于任何其他值仅在非严格相等下成立数学式比较 下null被转化为0undefined被转化为NaN。基于这五条规则下面逐题推导。逐题精解7 道题的结果与推导过程第 1 题5 4→true两个数字直接比较大小显然5大于4结果为true。这也是唯一一道纯数字比较的题用来确认你对比较运算符的基本认知没有偏差。第 2 题apple pineapple→false两个都是字符串按词典序逐字符比较。首位字符a与p比较在 Unicode 编码顺序中a比p小因此apple小于pineapple结果为false。第 3 题2 12→true注意这里不是数字 2 与 12 的比较而是字符串2与12的词典序比较。与第 2 题同理先比较首位字符2大于1算法在第一轮就结束因此2大于12结果为true。这题是最典型的陷阱题如果下意识把2和12当作数字 2 和 12就会得出相反的false。区分的关键在于两个操作数都是字符串时走的是词典序规则只有类型不同时才先做数字转换。第 4 题undefined null→true在非严格相等下JavaScript 有一条特殊规则null与undefined相等。它俩各自只等于对方不等于任何其他值。所以结果为true。这条规则只适用于相等性检查在、、中都不成立——这也正是第 57 题的关键。第 5 题undefined null→false严格相等不做任何类型转换。undefined和null属于不同的数据类型前者代表未被赋值后者代表空/未知二者在数据类型章节中各自构成独立类型所以直接返回false。同一对值为true、为false这就是是否做类型转换带来的本质差异。第 6 题null \n0\n→false与第 4 题同理null在下只与undefined相等不会等于任何其他值。因此无论右侧是\n0\n还是0、false、空字符串结果都是false。这里值得展开一点\n0\n是一个包含换行符的字符串在数字转换规则下去掉首尾空白后为0它本可以变为0。但在null 某值这个场景中相等性检查不会把null强制转成数字这是与 比较的重大区别详见下一节null 与 0 的矛盾结果因此转换根本不发生直接返回false。第 7 题null \n0\n→false右侧表达式\n0\n使用一元加号将字符串转为数字去掉首尾空白后得到0转换为数字0。于是比较变为null 0。由于严格相等不做类型转换null与数字0类型不同结果必然是false。即使改用null 0也依然是false见下文的坑点详解所以这题的答案非常稳定。从题目到原理三个最容易踩的坑前文的题目覆盖了比较规则的主干但 article.md 还专门讲解了三个反直觉的坑点值得单独拿出来剖析。坑点一null与 0 的矛盾结果alert( null 0 ); // (1) false alert( null 0 ); // (2) false alert( null 0 ); // (3) true这三行结果彻底打破了数学直觉既然null 0为true那么null 0和null 0中至少应有一个为true但事实是两者都为false。原因在于相等性检查与普通比较符 的代码逻辑是相互独立的。进行 比较时null被转化为数字0所以null 0为true、null 0为false进行相等性检查时null和undefined不做任何类型转换它们有自己独立的比较规则只与对方相等因此null 0为false。坑点二特立独行的undefinedalert( undefined 0 ); // (1) false alert( undefined 0 ); // (2) false alert( undefined 0 ); // (3) falseundefined与任何值比较几乎都是false原因有二(1)和(2)在数学式比较中undefined被转换为NaN而NaN是一个特殊的数值型值它与任何值进行比较都会返回false这一点在数据类型章节中也有说明(3)相等性检查下undefined只与null相等不会与其他值相等。坑点三非空字符串0的布尔值是truelet a 0; alert( Boolean(a) ); // false let b 0; alert( Boolean(b) ); // true alert( a b ); // true!a b为true是因为把0转成了数字0而Boolean(0)为true是因为布尔转换遵循空值规则——0、空字符串、null、undefined、NaN才转为false任何非空字符串都是true包括0和只含空格的 。同一对值在不同运算符下得到自相矛盾的结果这在 JavaScript 中是完全正常的走数字转换Boolean()走另一套规则。理解这一点就不会再被这类题迷惑。最佳实践如何避开比较陷阱研究这些例子的目的不是让你死记硬背古怪的规则而是掌握更可靠的规避方法。article.md 给出了两条核心建议尽量使用严格相等/!。它能清楚区分0与false、空字符串与false、null与undefined避免的类型转换带来隐性错误。对可能为null/undefined的变量不要使用 比较。除非你非常清楚自己在做什么否则永远不要用数学式比较一个取值可能是null/undefined的变量对于这类变量请按需要分别检查它的取值情况例如显式判断value null || value undefined。此外结合类型转换章节 的规则还有两点在实战中极易出错对undefined进行数字转换得到的是NaN而不是0。因此在处理可能未赋值的变量时Number(undefined)的结果是NaN参与数学比较会一路得到falseNaN与任何值包括它自己比较都为false。判断一个值是否为NaN应使用Number.isNaN()之类的专门手段而不是直接与NaN比较。总结回顾这 7 道练习题它们恰好覆盖了 JavaScript 值比较的全部核心规则比较运算符始终返回布尔值true/false字符串比较按词典顺序逐字符比较首位字符往往直接决定结果第 2、3 题不同类型的值比较时先被转化为数字true→1、false→0、null→0、undefined→NaN但不包括严格相等检查非严格相等下null和undefined相等且各自不等于任何其他值第 4、6 题严格相等不做类型转换类型不同立刻返回false第 5、7 题使用 时需特别小心变量可能为null/undefined的情况较好的做法是单独检查变量是否等于null/undefined。把这 7 道题连同背后的五条规则一起消化你就掌握了 JavaScript 比较系统的完整拼图。后续在学习字符串、类型转换、运算符等章节时你会不断遇到这些规则的应用场景届时它们会成为你写出健壮代码的直觉基础。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐现代 JavaScript 教程值的比较 7 道经典练习逐题精解含 null/undefined 陷阱现代 JavaScript 教程值的比较 7 道经典练习逐题精解含 null/undefined 陷阱 本篇文章以《现代 JavaScript 教程》z文档教程前端JavaScript 值的比较从相等性检查到 null/undefined 陷阱全解析JavaScript 值的比较从相等性检查到 null/undefined 陷阱全解析 本文是《现代 JavaScript 教程The Modern Jav文档教程前端JavaScript 比较运算符完全指南、、类型转换与 null/undefined 陷阱JavaScript 比较运算符完全指南、、类型转换与 null/undefined 陷阱 比较运算在 JavaScript 中无处不在条件判断、文档/教程前端上一篇Syncthing Docker 容器部署指南镜像构建、数据卷、网络模式与 GUI 安全配置实战下一篇Mermaid图表工具2025年最完整的流程图绘制指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进