console.log( [] == ![] ) // true
console.log( {} == !{} ) // false

在比较字符串、数值和布尔值的相等性时,问题还比较简单。但在涉及到对象的比较时,问题就变得复杂了。最早的ECMAScript中的相等和不相等操作符会在执行比较之前,先将对象转换成相似的类型。后来,有人提出了这种转换到底是否合理的质疑。最后,ECMAScript的解决方案就是提供两组操作符:

相等和不相等——先转换再比较 (==)
全等和不全等——仅比较而不转换 (===)

ECMAScript中相等操作符由两个等于号(==)表示,如果两个操作数相等,则返回true,这种操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性

在转换不同的数据类型时,对于相等和不相等操作符:在JS高程中一书中给出如下的基本转换规则

①、如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1;
②、如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
③、如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较

这两个操作符在进行比较时则要遵循下列规则。
①、null 和undefined 是相等的
②、要比较相等性之前,不能将null 和 undefined 转换成其他任何值
③、如果有一个操作数是NaN,则相等操作符返回 false ,而不相等操作符返回 true。重要提示:即使两个操作数都是NaN,相等操作符也返回 false了;因为按照规则, NaN 不等于 NaN
④、如果两个操作数都是对象,则比较它们是不是同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回 true;否则, 返回false

这里说一下题外话:[] 和 {} 都是属于引用类型,引用类型是存放在栈内存中的,而在堆内存中会有一个或者多个地址来指向这个栈内存相对应的数据。所以在使用 == 操作符的时候,对于引用类型的数据,比较的是地址,而不是真实的值。

现在来探讨 [] == ! [] 的结果为什么会是true

①、根据运算符优先级 ,! 的优先级是大于 == 的,所以先会执行 ![]

!可将变量转换成boolean类型,null、undefined、NaN以及空字符串('')取反都为true,其余都为false。

所以 ! [] 运算后的结果就是 false

也就是 [] == ! [] 相当于 [] == false

②、根据上面提到的规则(如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1),则需要把 false 转成 0

也就是 [] == ! [] 相当于 [] == false 相当于 [] == 0

③、根据上面提到的规则(如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较,如果对象没有valueOf()方法,则调用 toString()

而对于空数组,[].toString() -> '' (返回的是空字符串)

也就是 [] == 0 相当于 '' == 0

④、根据上面提到的规则(如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值

Number('') -> 返回的是 0

相当于 0 == 0 自然就返回 true了

总结一下:

[] == ! [] -> [] == false -> [] == 0 -> '' == 0 -> 0 == 0 -> true


那么对于 {} == !{} 也是同理的

关键在于 {}.toString() -> NaN(返回的是NaN)

根据上面的规则(如果有一个操作数是NaN,则相等操作符返回 false

总结一下:

{} == ! {} -> {} == false -> {} == 0 -> NaN == 0 -> false

那么相信大家对下面的两道题就信手拈来了


console.log( [] == !{} ) // true
console.log( {} == ![] ) // false

本文属于magic_xiang原创,转载需注明来源

来源:https://segmentfault.com/a/1190000017571299

JS中鲜为人知的问题: [] == ![]结果为true,而 {} == !{}却为false的更多相关文章

  1. JS中的逻辑运算符&&、||,位运算符|,&

    1.JS中的||符号: 运算方法: 只要“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值. 只要“||”前面为true,不管“||”后面是true还是fals ...

  2. JS中的逻辑运算符&&、||

    原文:JS中的逻辑运算符&&.|| 1.JS中的||符号: 运算方法: 只要"||"前面为false,不管"||"后面是true还是false, ...

  3. [转载]ASP.NET中TextBox控件设立ReadOnly="true"后台取不到值

    原文地址:http://www.cnblogs.com/yxyht/archive/2013/03/02/2939883.html ASP.NET中TextBox控件设置ReadOnly=" ...

  4. ASP.NET中TextBox控件设立ReadOnly="true"后台取不到值

    SP.NET中TextBox控件设置ReadOnly="true"H或Enabled=false后台取不到值 当TextBox设置了ReadOnly="true" ...

  5. 字符串0.在php和js中转换为布尔类型 值是false还是true

    在php 中 $a = '0'; $b = (bool)$a; var_dump($a);//输出false 在js中官方说明: Note:If the value parameter is omit ...

  6. js中的return,return true,return false小结

    return  函数执行到这句时会终结,并返回调用函数,而且把表达式的值作为函数的结果返回 return false 可以防止默认的事件行为.例如,默认情况下点击一个<a>元素,页面会跳转 ...

  7. js中return、return true、return false的区别

    一.返回控制与函数结果, 语法为:return 表达式; 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果  二.返回控制, 无函数结果,语法为:return;  在大多数情况下,为事件 ...

  8. js中return false,return,return true的使用方法及区别

    起首return作为返回keyword,他有下面两种返回体式格式 1.返回把握与函数成果 语法为:return 表达式; 语句停止函数履行,返回调用函数,而且把表达式的值作为函数的成果 2.返回把握无 ...

  9. js中return;、return true、return false;区别

    一.返回控制与函数结果, 语法为:return 表达式; 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果  二.返回控制, 无函数结果,语法为:return;  在大多数情况下,为事件 ...

随机推荐

  1. delphi实现圆角窗体[转]

    procedure TForm1.FormCreate(Sender: TObject); var hr :thandle; begin hr:=createroundrectrgn(1,1,widt ...

  2. GDI+在Delphi程序的应用 Photoshop色相饱和度明度功能

    本文用GDI+实现Photoshop色相/饱和度/明度功能,参照我的其它有关GDI+在 Delphi程序的应用的文章,代码也可供TBitmap使用. 有些人不喜欢,或者不太懂Delphi的BASM代码 ...

  3. 关于double的输入输出

    double定义的变量输入的时候一定要%lf输入,要是%f输入的话,得到的结果会是0 float输入的时候是%f 但是在输出的时候%lf和%f都可以输出 建议使用double类型时,用%lf输入,%f ...

  4. 常用的css解决方案

    一. css 2.x code 1. 文字换行  /*强制不换行*/ white-space:nowrap; /*自动换行*/ word-wrap: break-word; word-break: n ...

  5. uoj213 【UNR #1】争夺圣杯

    题目 设\(f_i\)表示所有长度为\(i\)的区间的最大值的和,求\(\bigoplus \sum_{i=1}^nf_i\) 不难发现随机数据非常好做 由于一个随机序列的前缀最大值期望只会变化\(\ ...

  6. 2019-2020 ICPC, NERC, Northern Eurasia Finals

    A. Apprentice Learning Trajectory rdc乱编的做法 考虑贪心,每次会选择结束时间最早的. 设当前时间为 \(x\),那么可以区间有两类 a) \(l_i \leq x ...

  7. C#& Screen 类&(&多&屏&幕&开&发)

    原文:C#& Screen 类&(&多&屏&幕&开&发) Screen 类 下面的代码示例演示如何使用 Screen 类的各种方法和属性. 该示 ...

  8. .Net Core JWT Bearer 的认证

    关于JWT原理在这不多说,主要由三部分组成:Header.Payload.Signature,有兴趣自己上网了解. 1.首先创建.Net Core 一个Api项目 2.添加 JWT 配置 2.1 修改 ...

  9. JS随机产生颜色

    <script> function selectForm(lowerValue,upperValue){ var choices=upperValue-lowerValue+1; retu ...

  10. JAVA数据结构之哈希表

    Hash表简介: Hash表是基于数组的,优点是提供快速的插入和查找的操作,编程实现相对容易,缺点是一旦创建就不好扩展,当hash表被基本填满的时候,性能下降非常严重(发生聚集引起的性能的下降),而且 ...