参考:MDN相等性判断
JavaScript提供三种不同的值比较操作:
- === ,严格相等比较 (也被称作”strict equality”, “identity”, “triple equals”)
- ==,抽象相等比较 (“loose equality”,”double equals”)
Object.is
(ECMAScript 2015/ ES6 新特性)
Moral of the story:
Always use 3 equals unless you have a good reason to use 2.
能用===
就用===
!!!
===
全等操作符比较两个值是否相等,两个被比较的值在比较前都不进行隐式转换。
如果两个被比较的值具有不同的类型,这两个值是不全等的。具体规则:
- 如果类型不同,就[不相等]
- 如果两个值都是null,或者都是undefined,那么[相等]。
- 如果两个都是数值,并且是同一个值,那么[相等]。但是+-0和NaN要特殊对待
- +0,-0,0视作相等
- NaN与任何值都不等,包括NaN
- 如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。
- 如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
1 | // 这些是===符合预期的情况 |
Object.is
Object.is的行为方式与===
相同,但是对于NaN和-0和+0进行特殊处理
===
- +0,-0,0视作相等
- NaN与任何值都不等,包括NaN
- Object.is
- +0和0相等,和-0不相等
- NaN和NaN相等
1 | // 行为方式与===相同 |
+0 -0
+0和-0的区别
- +0是0,-0是别的
- 主要是浮点数表示中符号位不同
- 表现不同:加减乘除运算
1 | +0 + (+0) = +0 |
判断+-0
1 | //判断是否为+0 |
+0和-0的应用场景
隐式类型转换:String转Number用-0,此外*1或/1也行
1 | "123"+0 // '1230' |
NaN
NaN
是一个全局对象的属性。
NaN
属性的初始值就是 NaN,和 Number.NaN
的值一样。在现代浏览器中(ES5 中), NaN
属性是一个不可配置(non-configurable),不可写(non-writable)的属性
NaN出现的情况
编码中很少直接使用到 NaN
。通常都是在计算失败时
- 作为 Math 的某个方法的返回值出现的(例如:
Math.sqrt(-1)
) - 或者尝试将一个字符串解析成数字但失败了的时候(例如:
parseInt("blabla")
)。
判断一个值是否是 NaN
返回false的情况
- 通过
==
、===
与其他任何值比较都将不相等, 包括与其他NaN
值进行比较。
返回true的情况
- Object.is(NaN, NaN)
Number.isNaN()
或isNaN()
函数
在执行自比较之中:也只有 NaN
不等于它自己。
==
在比较前将两个被比较的值转换为相同类型。
在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符 === 的比较方式
如果两个值类型相同,进行 === 比较。
- 注意NaN和NaN,规定[不相等]!
如果两个值类型不同。根据下面规则进行类型转换再比较:
如果一个是null、一个是undefined,那么[相等]
- null、undefined和其他数据类型比较都[不相等]
如果其中之一为Number
- 另一个是String,就转成Number判断
- 返回值可能是NaN或数值
- 另一个是Boolean,就转成Number判断
- true->1,false->0
- 另一个是Object,调用ToPrimitive比较
- 另一个是String,就转成Number判断
如果是String和Boolean
- 都转化成Number
如果是Object
- 调用ToPrimitive比较
Number
Number
对象主要用于:
使用new操作符
new,返回对象,由Number构造函数产生
不new,返回Number类型的一个数值
1 | new Number(value); |
ToPrimitive
Symbol.toPrimitive
这是一个对象的内置函数属性,无法从外部调用,但是我们可以通过触发隐式类型转换观察它的行为
1 | var obj1 = {}; |
可以重写Symbol.toPrimitive属性,hint
参数的取值是 "number"
、"string"
和 "default"
中的任意一个。
1 | // 接下面声明一个对象,手动赋予了 Symbol.toPrimitive 属性,再来查看输出结果 |
转换规则
hint
参数是"string"
,Object->String
判断对象中有没有toString()
方法
有,调用
toString()
方法。- 如果返回一个原始值,非字符串的转化为字符串,返回字符串
没有,或者
toString()
返回一个非原始值,那么js会调用valueOf()
方法。- 如果返回一个原始值,非字符串的转化为字符串,返回字符串
否则,js抛出一个类型错误异常。
hint
参数是"number/default"
,Object->Number
判断对象中有没有valueOf()
方法
- 有,调用
valueOf()
方法- 返回一个原始值,则js会将其转换为数字(如果需要的话)并返回这个数字。
- 没有,如果对象具有
toString()
方法,则调用- 返回一个原始值(字符串直接量),则js将其转换为数字类型,并返回这个数字。
- 否则,js抛出一个类型错误异常。
判断
参考:JS比较表
下面的情况==会输出什么?
1 | NaN==NaN // false, NaN与任何值都不等 |