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

在比较字符串、数值和布尔值的相等性时,问题还比较简单。但在涉及到对象的比较时,问题就变得复杂了。

比较规则

最早的ECMAScript中的相等和不相等操作符会在执行比较之前,先将对象转换成相似的类型。后来,有人提出了这种转换到底是否合理的质疑。最后,ECMAScript的解决方案就是提供两组操作符:

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

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

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

转换规则

在转换不同的数据类型时,对于相等和不相等操作符,JS遵循如下的基本转换规则:

  1. 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1
  2. 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
  3. 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较。这两个操作符在进行比较时则要遵循下列规则:
    1. nullundefined 是相等的
    2. 要比较相等性之前,不能将null undefined转换成其他任何值
    3. 如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回 true。重要提示:即使两个操作数都是NaN,相等操作符也返回 false了;因为按照规则,NaN不等于 NaN
    4. 如果两个操作数都是对象,则比较它们是不是同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回 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

JavaScript 探究[] == ![]结果为true,而 {} == !{}却为false的更多相关文章

  1. JS规则 较量较量(比较操作符) 两个操作数通过比较操作符进行比较,得到值为真(true)和假(false)。【>; <; >=; <=; !=;==】

    较量较量(比较操作符) 我们先来做道数学题,数学考试成绩中,小明考了90分,小红考了95分,问谁考的分数高? 答: 因为"95 > 90",所以小红考试成绩高. 其中大于号& ...

  2. request.getSession(true)和request.getSession(false)的区别

    request.getSession(true)和request.getSession(false)的区别   request.getSession(true):若存在会话则返回该会话,否则新建一个会 ...

  3. python练习:编写一个函数isIn,接受两个字符串作为参数,如果一个字符串是另一个字符串的一部分,返回True,否则返回False。

    python练习:编写一个函数isIn,接受两个字符串作为参数,如果一个字符串是另一个字符串的一部分,返回True,否则返回False. 重难点:定义函数的方法.使用str类型的find()函数,可以 ...

  4. python中1 is True 的结果为False,is判断与==判断的区别

    python中1 is True 的结果为False,而1 == True的结果为True. python中True的数值就是1,那为什么1 is True 的结果为False呢? 因为is判断和== ...

  5. includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

    注意:对象数组不能使用includes方法来检测. JavaScript Demo: Array.includes() var array1 = [1, 2, 3]; console.log(arra ...

  6. 两对整数明明完全一样,为何一个输出true,一个输出false?&&神奇代码(StrangeIntegerBehavior.java)输出诡异的结果,原因何在

    下面有一段代码: public class Main {     public static void main(String[] args) {                   Integer ...

  7. 转:request.getSession(true)和request.getSession(false)的区别

    1.转自:http://wenda.so.com/q/1366414933061950?src=150 概括: request.getSession(true):若存在会话则返回该会话,否则新建一个会 ...

  8. 为什么使用正则test( )第一次是 true,第二次是false?

    今天朋友问我一个问题,我现在需要多次匹配同一个内容,但是为什么我第一次匹配,直接是 true,而第二次匹配确实 false 呢? var s1 = "MRLP"; var s2 = ...

  9. 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false?

    今天朋友问我一个问题,我现在需要多次匹配同一个内容,但是为什么我第一次匹配,直接是 true,而第二次匹配确实 false 呢? var s1 = "MRLP"; var s2 = ...

  10. JavaScript中给onclick绑定事件后return false遇到的问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. unity 新input system 鼠标点在ui上检测的两种方法

    哪种有用就用哪种.EventSystem.current.IsPointerOverGameObject()有可能不好使. using System.Collections.Generic; usin ...

  2. 【题解】P2627 [USACO11OPEN] Mowing the Lawn G

    [题解]P2627 [USACO11OPEN] Mowing the Lawn G 题目跳转 数据量比较大,暴力肯定是不行的.只能考虑用动态规划的方式来做. 这道题有许多dp设计的思路,这里提供两个: ...

  3. apache 的下载与配置

    一,下载: 打开apache的官方网站,http://www.apache.org/   拉到网站的最下面,如图所示: 点击HTTP Server链接,对 Apache httpd 2.4.43 Re ...

  4. C# Afroge摄像头翻转90

    1.dll和命名空间就不在此列举了,如下只是将转换方法介绍: 第一个函数: public void Rotate90() { // 计算角度,类变量 //dAngle = dAngle + 90; / ...

  5. 申请并部署免费的 SSL/TLS 证书

    对于囊中羞涩的我们来说,只要能白嫖,就绝不乱花钱.惯常申请免费 SSL/TLS 证书的途径有: 各大云服务平台限量提供.比如阿里云会给每个账号每年 20 个证书的申请额度.缺点是不支持泛域名,一年后须 ...

  6. Python保姆级教程 数据类型—新手小白入门必看系列

    推荐使用压缩软件和杀毒软件 7 - zip 使用火绒 一.基本数据类型与变量(上) 2.1 注释 优点: 代码说明 没注释的代码 有注释的代码 不让解释器执行注释的那句话 2.2 单行注释 单行注释快 ...

  7. 7.18考试总结(NOIP模拟19)[u·v·w]

    我们不是狼,我们只是长着獠牙的羊...... 前言 我真 TM 爱死 \(\frac{1}{4}\) 了. 老实说,这套题是真恶心,第一题还有一点思路,到了后面是一点都搞不定了. 总的来说,主要原因是 ...

  8. FFmpeg开发笔记(二十八)Linux环境给FFmpeg集成libxvid

    ​XviD是个开源的视频编解码器,它与DivX一同被纳入MPEG-4规范第二部分的视频标准,但DivX并未开源.早期的MP4视频大多采用XviD或者DivX编码,当时的视频格式被称作MPEG-4.现在 ...

  9. String Record

    T1. P5840 算法:ACAM+BIT+树链剖分 自然地,我们会对 \(s_i\) 建 ACAM,然后建出一颗 fail 树. 此时我们考虑集合内加入一个新的字符串.每一个匹配到的点我们都会给从这 ...

  10. 企业级私有仓库Harbor

    仓库的概念也就是用于存储,docker仓库用于存储镜像. 镜像构建完成后,很容易可以在宿主机上运行,但是如果要在其他服务器上运行,则需要考虑镜像的分发,存储的问题. 共有/私有/仓库 Docker R ...