!! 与 == 的转换规则一样吗?
结论是不一样,举一个例子:
'true' == true // false
!!'true' // true
可以看出执行 ==
和 !!
操作时,会将同样的字符串 'true'
转换成不一样的结果。
接下来我们看一下 ECMAScript 的规范。
==
- 如果
Type(x)
与Type(y)
类型相同, 那么- 如果
Type(x)
是Undefined
, 返回true
. - 如果
Type(x)
是Null
, 返回true
. - 如果
Type(x
) 是Number
, 那么- 如果 x 是
NaN
, 返回false
. - 如果 y 是
NaN
, 返回false
. - 如果 x 与 y 是相同的
Number
, 返回true
. - 如果 x 是
+0
并且 y 是−0
, 返回true
. - 如果 x 是
−0
并且 y 是+0
, 返回true
. - 返回
false
.
- 如果 x 是
- 如果
Type(x)
是String
, 那么返回true
, 如果 x 和 y 是相同的序列 (长度一样,相同下标的字符一样). 否则, 返回false
. - 如果
Type(x)
是Boolean
, 返回true
如果 x 和 y 都是true
或者都是false
. 否则, 返回false
. - 返回
true
如果 x 和 y 引用了相同的对象 (地址). 否则, 返回false
.
- 如果
- 如果 x 是
null
并且 y 是undefined
, 返回true
. - 如果 x 是
undefined
并且 y 是null
, 返回true
. - 如果
Type(x)
是Number
并且Type(y)
是String
, 返回x == ToNumber(y)
的比较结果。 - 如果
Type(x)
是String
并且Type(y)
是Number
, 返回ToNumber(x) == y
的比较结果。 - 如果
Type(x)
是Boolean
, 返回ToNumber(x) == y
的比较结果。 - 如果
Type(y)
是Boolean
, 返回x == ToNumber(y)
的比较结果。 - 如果
Type(x)
是String
或Number
并且Type(y)
是Object
,返回x == ToPrimitive(y)
的比较结果。 - 如果
Type(x)
是Object
并且Type(y)
是String
或Number
,返回ToPrimitive(x) == y
的比较结果。 - 返回
false
.
简单来说,当两者类型不同,并且都为基本类型的时候,优先将他们转换成 Number
进行比较,两者为基本类型与对象时,获取对象的原始值(primitive),也就是按顺序与 toString
和 valueOf
的结果进行比较。
!!
先看一下 !
操作符的行为:
- 用
expr
表示UnaryExpression
一元表达式的值。 - 让
oldValue
成为 ToBoolean(GetValue(expr
)). - 如果
oldValue
是true
, 返回false
. - 返回
true
.
关键在 ToBoolean
这个操作上,行为如表所示:
参数类型(ToBoolean(arg)) | 结果 |
---|---|
undefined | false |
null | false |
boolean | 和传入的参数 arg 一样 |
number | +0 、-0 或 NaN 时为 false ,其他情况为 true |
string | '' 时为 false ,其他情况为 true |
object | true |
!
操作符用于根据以上规则,将表达式结果转换为 Boolean
再取反,那么 !!
实际上是在 !
的基础上再一次取反,所以结果就是“将表达式结果转换成 Boolean
”,!!
只是一个取巧的操作。
那么可以看出,!!
和 ==
的转换规则并不同,!!
并不会将值优先转换成 Number
,而是直接转换为 Boolean
,这就和调用 Boolean()
函数的时候一样。