当前位置: 首页 > news >正文

=== 和 == 的规则及原理

文章目录

  • 一、前言
  • 二、设计的原因(个人理解)
  • 三、== 转换规则
    • 3.1 == 相同类型的比较
    • 3.2 == 不同类型的比较
  • 四、== 和 === 的代码简单实现
    • 4.1 === 实现
    • 4.2 == 实现

一、前言

前段时间在面试时,被问到 JavaScript 中 ===== 的区别。
当时就简单的回答了一下八股,== 会进行类型转换再比较,=== 不会进行转换,必须值和类型都相同。这个答案没什么问题,但是感觉理解有些太浅了,所以我就在想:

  1. JS为什么要设计这两个功能比较重复的比较运算符呢?
  2. == 的隐式类型转换到底发生了什么?
  3. 底层是什么机制导致的这种差别呢?

今天我就围绕着三个问题说一下自己查到的和理解。

二、设计的原因(个人理解)

先看JS的历史背景,在1995年由 Brendan Eich 在 10 天里快速设计出来的。当时的目标可能就是为了能够快速在浏览器中快速实现页面的交互,所以当时的设计目标不具备很强的严谨性。所以 == 的实现会自动“兜底”,就是会进行隐式类型转换。

在ES3之后为了弥补 == 的问题,在规范中添加了 === (严格相等), 不做隐式转换,要求类型和值完全一致。

为什么不直接废掉 == ?

JS 已经在浏览器里广泛运行,改动会破坏成千上万的网站。而且在某些场景中 == 也有好处,比如:

if(x == null) {// 等价于 x === null || x === undefined
}

这是一种社区里仍然存在的“惯用法”。

三、== 转换规则

===(严格相等比较) 逻辑很简单:

  • 类型不同 -> 直接 false
  • 类型相同 -> 比较值(对象比较引用)

==(抽象相等比较) 逻辑由于有隐式类型转换,相对麻烦一些,根据MDN中的描述,简单来梳理一下 == 的转换规则:

3.1 == 相同类型的比较

如果两个操作数类型相同,比较规则如下:

对象: 只有当他们引用同一个对象时,结果才是 true。

{} == {} // false, 不同引用
let a = {};
let b = a;
a == b; // true, 同一引用

字符串: 必须字符和顺序完全相同。

'abc' == 'abc' // true
'abc' == 'cba' // false

数字: 数值相同则返回 true。

  • 特殊情况:+0 == -0 => true
  • NaN 永远不等于任何值(包括自己)
0 == -0 // true
NaN == NaN // falses

布尔: 只有在都为true或都为false时返回true。

true == true   // true
false == true  // false

大整数(BigInt): 值相同即为 true

1n == 1n // true

符号(Symbol): 不是同一个符号引用

Symbol() == Symbol() // false
const s1 = Symbol()
const s2 = s1;
s2 == s1 // true

3.2 == 不同类型的比较

当类型不同,会进行以下规则:

null 和 undefined

  • 只有 null == undefined 为 true。
  • 与其他任何值比较都为 false。
null == undefined // true
null == 0         // false

布尔 vs 其他

  • 布尔会先转为数字(true → 1,false → 0)。
true == 1  // true
false == 0 // true

字符串 vs 数字

  • 字符串会转为数字再比较。
'42' == 42  // true
'abc' == NaN // false

对象 vs 原始值

  • 对象会先用 ToPrimitive 转换为原始值(通过 Symbol.toPrimitive、valueOf、toString 等)。
[] == ''  // true ([] → '')
[] == 0   // true ([] → '' → 0)
[1] == 1  // true ([1] → '1' → 1)

这部分涉及 ToPrimitive (把对象转换原始值)这个抽象操作,请看另一篇文章。

数字 vs BigInt

  • 按数值比较。
  • 如果数字是 ±Infinity 或 NaN,则结果为 false。
1n == 1   // true
1n == NaN // false

字符串 vs BigInt

  • 尝试把字符串转为 BigInt 再比较。

  • 转换失败则返回 false。

'10' == 10n  // true
'abc' == 10n // false

符号 vs 非符号

  • 永远返回 false。
Symbol() == 'symbol' // false

四、== 和 === 的代码简单实现

4.1 === 实现

function strictEqual(x, y) {// 类型不同直接 falseif (typeof x !== typeof y) return false;return x === y; // 值比较
}

4.2 == 实现

在 ECMAScript® Language Specification §7.2.14 里,== 的比较规则大概是这样:

  1. 类型相同 → 按 === 比较。
  2. null 和 undefined → 相等。
  3. number 和 string → string → number,再比较。
  4. boolean → 转换成 number,再比较。
  5. object 和原始值 → object 转换成原始值(调用 ToPrimitive),再比较。
  6. 其他情况 → 不相等。
// ToPrimitive 转换(简化实现)
// 实际规范有 PreferredType 参数,这里我们用默认的
function toPrimitive(input) {if (typeof input !== "object" || input === null) return input;// 尝试 valueOfif (typeof input.valueOf === "function") {const val = input.valueOf();if (typeof val !== "object") return val;}// 尝试 toStringif (typeof input.toString === "function") {const val = input.toString();if (typeof val !== "object") return val;}throw new TypeError("Cannot convert object to primitive");
}function abstractEqualityComparison(x, y) {// 1. 类型相同 → 用 ===if (typeof x === typeof y) {return x === y;}// 2. null 和 undefinedif (x == null && y == null) {return true;}// 3. number 和 stringif (typeof x === "number" && typeof y === "string") {return abstractEqualityComparison(x, Number(y));}if (typeof x === "string" && typeof y === "number") {return abstractEqualityComparison(Number(x), y);}// 4. boolean → 转 numberif (typeof x === "boolean") {return abstractEqualityComparison(Number(x), y);}if (typeof y === "boolean") {return abstractEqualityComparison(x, Number(y));}// 5. object 和 原始值if ((typeof x === "object" && x !== null) && (typeof y !== "object" || y === null)) {return abstractEqualityComparison(toPrimitive(x), y);}if ((typeof y === "object" && y !== null) && (typeof x !== "object" || x === null)) {return abstractEqualityComparison(x, toPrimitive(y));}// 6. 其他情况return false;
}console.log(abstractEqualityComparison(1, '1')); // true
console.log(abstractEqualityComparison(true, 1)); // true
console.log(abstractEqualityComparison(null, undefined)); // true
console.log(abstractEqualityComparison([], 0)); // true
console.log(abstractEqualityComparison([1,2], "1,2")); // true
console.log(abstractEqualityComparison({}, "[object Object]")); // true
console.log(abstractEqualityComparison(0, false)); // true
console.log(abstractEqualityComparison(NaN, NaN)); // false

文章转载自:

http://U5mWQfyt.Lcbnb.cn
http://AcelWJHP.Lcbnb.cn
http://tArZBhOJ.Lcbnb.cn
http://gVJQG9mK.Lcbnb.cn
http://N4nEkh4c.Lcbnb.cn
http://neQ405Bu.Lcbnb.cn
http://DCiHfXA8.Lcbnb.cn
http://JOg5uhDS.Lcbnb.cn
http://kcxLwFdP.Lcbnb.cn
http://kHdEhyTf.Lcbnb.cn
http://h0LA8vqE.Lcbnb.cn
http://lDdzxEmw.Lcbnb.cn
http://QUlCDQny.Lcbnb.cn
http://0lBndMWd.Lcbnb.cn
http://r2MtRWjU.Lcbnb.cn
http://zGqPz4ED.Lcbnb.cn
http://Majfosyd.Lcbnb.cn
http://Ah2cc7Ex.Lcbnb.cn
http://YFKTv3oG.Lcbnb.cn
http://Y5o2ExzP.Lcbnb.cn
http://vuZszZHG.Lcbnb.cn
http://3yvmRCYl.Lcbnb.cn
http://RHX60gI8.Lcbnb.cn
http://qKmH2Szs.Lcbnb.cn
http://lg9miJrW.Lcbnb.cn
http://YiSBfCv8.Lcbnb.cn
http://mOrHj31g.Lcbnb.cn
http://zuf3z3Oj.Lcbnb.cn
http://RHHzY1If.Lcbnb.cn
http://AUMUrn1t.Lcbnb.cn
http://www.dtcms.com/a/372302.html

相关文章:

  • Python:基于LangChain的AI Agent(智能代理)应用开发实践
  • Java ConcurrentHashMap 底层原理与线程安全机制深度解析
  • 基于SpringBoot+Vue的健身房管理系统的设计与实现(代码+数据库+LW)
  • 批量标准化(Batch Normalization):为什么它能让深度学习模型跑得更快、更稳?
  • 1分钟使用ssh-keygen生成RSA公私钥
  • 【从零开始java学习|第十一篇】构造一个JavaBean
  • 侠盗飞车圣安地列斯原版中文资源,适配Win10/11,不用安装!
  • Linux —— 虚拟进程地址空间
  • 负载均衡器如何自动将故障实例从服务列表中剔除
  • MySQL软件架构概述
  • 【面试】AI大模型应用原理面试题
  • postman接口功能测试
  • Java数据结构 - 顺序表模拟实现与使用
  • 【秋招笔试】2025.09.04携程秋招
  • PyPI 镜像源选择与 pipenv/poetry 加速配置(含实战与避坑)
  • 如何设计本地缓存、有哪些坑需要避免
  • 人力资源管理的思维方法学习笔记1
  • 【面试向】边缘计算基础介绍
  • digitalworld.local: TORMENT
  • MySQL数据库专用命令详细使用指南
  • Python3.12-slim版本
  • AI 生成式艺术重塑动漫角色创作:从技术逻辑到多元可能性(三)
  • 【面试向】元宇宙介绍
  • 硬件开发(4)—ARM裸机体系结构
  • Stream API三巨头:filter、map、collect
  • NAS可以干啥?好玩吗?
  • GDAL 在 Python 中的开发起步
  • RK3568编译linux内核遇到问题总结
  • React学习教程,从入门到精通, React 样式语法知识点与案例详解(13)
  • BiFormer注意力机制YOLOV8