JS鲜为人知的问题之[] == ![]结果为true、而{} == !{}却为false

 更新时间:2021年05月08日 09:49:27   作者:magic_xiang  
这篇文章主要给大家介绍了关于JS鲜为人知的问题之[] == ![]结果为true、而{} == !{}却为false的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
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

总结

到此这篇关于JS鲜为人知的问题之[] == ![]结果为true、而{} == !{}却为false的文章就介绍到这了,更多相关JS [] == ![]结果为true内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript页面倒计时功能完整示例

    JavaScript页面倒计时功能完整示例

    这篇文章主要介绍了JavaScript页面倒计时功能,结合完整实例形式分析了javascript计时器、时间运算相关操作技巧,需要的朋友可以参考下
    2019-05-05
  • JS设计模式之访问者模式的用法详解

    JS设计模式之访问者模式的用法详解

    JS访问者模式是一种行为型设计模式,用于将算法与对象结构分离, 该模式允许你定义新的操作(访问者)而无需修改现有对象结构(被访问者), 通过这种方式,你可以在不改变对象结构的情况下添加新的操作,本文就给大家详细的讲讲JS访问者模式的用法
    2023-08-08
  • JS正则表达式之非捕获分组用法实例分析

    JS正则表达式之非捕获分组用法实例分析

    这篇文章主要介绍了JS正则表达式之非捕获分组用法,结合实例形式详细分析了正则表达式中非捕获分组的概念、功能、使用方法与相关注意事项,需要的朋友可以参考下
    2016-12-12
  • js实现编辑div节点名称的方法

    js实现编辑div节点名称的方法

    这篇文章主要介绍了js实现编辑div节点名称的方法,可实现针对div节点名称的编辑及样式的选择效果,并且分别针对IE与FF浏览器的样式进行了选择与控制,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • js克隆对象、数组的常用方法介绍

    js克隆对象、数组的常用方法介绍

    以下几种方法都是复制一个新的对象或者数组,但是如果直接通过parent【iframe情况】的方式去父窗口的对象的时候会有问题,感兴趣的朋友可以了解下
    2013-09-09
  • 如何判断微信内置浏览器(通过User Agent实现)

    如何判断微信内置浏览器(通过User Agent实现)

    在进行微信公众账号开发的时候,需要知道当前的浏览器是微信内置的浏览器,那么如何判断呢?这是就只有通过浏览器的User Agent来进行判断了
    2014-09-09
  • JS监听浏览器关闭、刷新及切换标签页触发事件代码示例

    JS监听浏览器关闭、刷新及切换标签页触发事件代码示例

    浏览器是客户端,客户端的操作服务器是监听不到的,所以可以用js来监听,js代码监听浏览器关闭或者刷新,这篇文章主要给大家介绍了关于JS监听浏览器关闭、刷新及切换标签页触发事件的相关资料,需要的朋友可以参考下
    2023-11-11
  • Bootstrap每天必学之响应式导航、轮播图

    Bootstrap每天必学之响应式导航、轮播图

    Bootstrap每天必学之响应式导航、轮播图,本文的主要内容是在导航条的下方做一张轮播图,自动播放最新的重要动态,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • JS实现多级菜单中当前菜单不随页面跳转样式而发生变化

    JS实现多级菜单中当前菜单不随页面跳转样式而发生变化

    本文介绍了JQuery巧妙实现多级菜单中当前菜单不随页面跳转样式发生变化,实现方法非常简单,感兴趣的朋友一起看看吧
    2017-05-05
  • 分享8个JavaScript库可更好地处理本地存储

    分享8个JavaScript库可更好地处理本地存储

    这篇文章主要介绍了分享8个JavaScript库可更好地处理本地存储,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10

最新评论