Javascript的细节(三):抽象相等,严格相等和其他
发表于更新于阅读时长 2 分钟在ES2015中一共提供了四种相等,下文将一一介绍
1. 严格等于(===)
除了===之外,还用在Array.prototype.indexOf
,Array.prototype.lastIndexOf
和switch ... case
语句中
显然的,在使用严格等于时,先比较两个值的类型,如果不同则不相等
如果两值的类型不为Number
,则只有他们的值相等时才相等
若它们的类型为Number
时,则有两个特例
- NaN与任何值都不等
- +0与-0相等
当然还会遇到浮点数精度问题
总而言之用这个!
2.抽象相等(==)
也可以叫宽松相等,会把两个值转换成可以比较的类型之后再比较
转换的规则非常复杂,但是可以抽象成如下规则:
-
Javacript 中的值可以分为两种,原始值(包括
undefined
null
Number
String
Boolean
和 ES6 新增的Symbol
)和Object
-
undefined
和null
只互相相等,和其他任何类型的值都不等 -
Symbol
和任何类型的值都不等 -
除了1 2中提及的类型,剩下三种原始类型互相比较都会被转换成
Number
类型再进行比较 -
而一个
Object
被用来和原始值进行比较时,会被转换成原始值,步骤如下- 先尝试调用该
Object
的toString
方法 - 如果1不存在,再尝试调用该
Object
的valueOf
方法 - 如果都不存在或者得到的值不是原始值则抛错
- 最后将得到的值进行宽松相等(==)比较
- 先尝试调用该
-
两个
Object
互相比较时,只有为对同一个Object
的引用时才相等
一个小例外是document.all
,出于历史原因,虽然在现代浏览器中访问它的值是一个HTMLCollection
,但是它和undefined
null
宽松相等
是大部分 JavaScript 笑话的来源
3.同值相等
同值相等只有在两个值在任何环境下都可以发挥出同样的功能,即满足里氏替换原则
Object.is使用了这个机制,在对Object
的{ writable: false }
写入判断是否会抛错的也是这个机制
它和严格相等的主要区别在于
- +0和-0不相等
NaN
和NaN
相等
4.同值零相等
和上一个类似,除了+0和-0在该机制中相等。或者说和严格相等类似,除了NaN
和NaN
在该机制中相等
ES6中引入的Map
和Set
中使用该机制判断来是否是同一个key