Hello,大家好,我是 Sunday。
我们知道在 JS 中有两种判断相等的方式,即:== 和 ===。并且很多同学会认为“==”运算符(通常称为“松散相等”或简称“相等”)是不精准的。
“==”不关心数据类型,只关心值
例如如下代码:
1 == '1' // true
而“===”运算符,即“严格相等”,可以有效地验证操作数的值和类型:
1 === '1' // false
但是这种理解真的是完全正确的吗?最近有一个同学在面试的时候被深入问到了这个问题,咱们来看一下:
先说结论,其实:“==”和“===”这两个运算符都优先考虑数据类型,并在执行各自的算法之前执行类型检查。事实上,即使是“==”运算符在评估值之前也会验证类型。
根据 JavaScript 规范参考 ECMAScript 262 文档,概述了 IsLooselyEqual算法 ,负责处理“==”操作。这里说明了涉及 14 个步骤的综合过程。值得注意的是,这个过程大量涉及类型检查,如涉及Type(x)的初始步骤所证明的那样,并引入强制作为整个操作的重要方式。
图片
下方描述为翻译后的结果
// 在线地址:https://262.ecma-international.org/14.0/?_gl=1*1ddd25w*_ga*MTAzMTk1MjUwNS4xNzA0MTgwNDk0*_ga_TDCK4DWEPP*MTcwNDE4MDQ5NC4xLjAuMTcwNDE4MDQ5NC4wLjAuMA..&_ga=2.72864531.1838071013.1704180495-1031952505.1704180494#sec-islooselyequal7.2.14 松散相等 ( x, y )抽象操作 IsLooselyEqual 接受参数 x(ECMAScript 语言值)和 y(ECMAScript 语言值),并返回包含布尔值的正常完成或抛出完成。 它提供 == 运算符的语义。 调用时它执行以下步骤:1. 如果 Type(x) 是 Type(y),则A。 A。 返回 IsStrictlyEqual(x, y)。2. 如果 x 为 null 并且 y 未定义,则返回 true。3. 如果 x 未定义且 y 为 null,则返回 true。4. 注意:此步骤已在 B.3.6.2 节中替换。5. 如果 x 是数字且 y 是字符串,则返回! IsLooselyEqual(x, !ToNumber(y))。6. 如果 x 是字符串且 y 是数字,则返回! IsLooselyEqual(!ToNumber(x), y)。7. 如果 x 是 BigInt 并且 y 是 String,则A。 令 n 为 StringToBigInt(y)。b. 如果 n 未定义,则返回 false。C。 返回 ! IsLooselyEqual(x, n)。8. 如果 x 是 String 并且 y 是 BigInt,则返回! IsLooselyEqual(y, x)。9. 如果 x 是布尔值,则返回! IsLooselyEqual(!ToNumber(x), y)。10. 如果 y 是布尔值,则返回! IsLooselyEqual(x, !ToNumber(y))。11. 如果 x 是字符串、数字、BigInt 或符号并且 y 是对象,则返回! IsLooselyEqual(x, ? ToPrimitive(y))。12. 如果 x 是对象并且 y 是字符串、数字、BigInt 或符号,则返回! IsLooselyEqual(? ToPrimitive(x), y)。13. 如果 x 是 BigInt 并且 y 是 Number,或者如果 x 是 Number 并且 y 是 BigInt,则A。 A。 如果 x 不是有限的或 y 不是有限的,则返回 false。b. b. 如果 ℝ(x) = ℝ(y),则返回 true; 否则返回 false。14. 返回 false。
强制转换涉及将一种类型的值转换为另一种类型,可以通过有意操作显式转换,也可以通过 JavaScript 机制隐式转换,无需任何用户干预。
另外一个有趣的方法,当两种类型匹配时,将使用 IsStrictlyEqual 算法(步骤 1.a),该算法与“===”运算符使用的算法完全相同。
图片
翻译之后为:
// 在线地址:https://262.ecma-international.org/14.0/?_gl=1*1ddd25w*_ga*MTAzMTk1MjUwNS4xNzA0MTgwNDk0*_ga_TDCK4DWEPP*MTcwNDE4MDQ5NC4xLjAuMTcwNDE4MDQ5NC4wLjAuMA..&_ga=2.72864531.1838071013.1704180495-1031952505.1704180494#sec-isstrictlyequal7.2.15 IsStrictlyEqual(x,y)抽象操作 IsStrictlyEqual 接受参数 x(ECMAScript 语言值)和 y(ECMAScript 语言值)并返回布尔值。 它提供 === 运算符的语义。 调用时它执行以下步骤:1. 如果 Type(x) 不是 Type(y),则返回 false。2. 如果 x 是一个数字,那么A。 返回 Number::equal(x, y)。3. 返回 SameValueNonNumber(x, y)。
让我们深入研究 IsLooselyEqual的第五步(如果 x 是数字且 y 是字符串,则返回! IsLooselyEqual(x, !ToNumber(y))):
图片
根据提供的代码片段
1 == "1" // true // x 是数字 (1) // y 是字符串 ("1")
此处,调用 ToNumber (y)函数时会发生隐式 强制转换。此强制过程将值(y,即“1”)从其原始类型(在本例中为String)转换为不同的类型(在本例中为Number)。在比较值之前,此步骤涉及类型检查和强制,将两个值对齐到同一类型(Number),从而实现两个数字之间的直接比较。
1 == "1" // true //步骤 1。// -> 检查两种类型// -> 两种类型不同// -> 执行 IsLooselyEqual 的后续步骤//步骤 2。 // -> "1 " (String) 将变成 1 (Number) - 强制机制//Step 3. // -> 将值 1(数字,从左侧)与值 1(数字,在右侧)进行比较
在这种情况下,严格相等运算符将返回 false,如前面提供的内容所示。由于两种类型不同,因此 === 会判定为 false:
1 === "1" // false //步骤 1. // -> 检查两种类型// -> 两种类型不同// -> 结束进程,返回 false
两个比较运算符都会检查类型,但松散的相等运算符(==) 需要执行额外的步骤。
本文链接:http://www.28at.com/showinfo-26-83277-0.htmlJS 中 == 不检查类型?不,你错了!
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: Python备份数据有哪些库