看完这篇,“==”不是问题
前言
此方法的总结起因于《You dont know JS》,在我看到“==”那里的时候,觉得作者只是在罗列ECMA的内容,包括在最后他罗列了二十多个特殊情况,也没有解释为什么会这样?
关于在ECMA的“==”内容我也有去看,上面只写了很少的一部分。大部分的特殊情况比如,“undefined==0”,并没有给出一定的规范。
可能有人觉得平时不怎么用“==”,我为什么要了解它?因为“>”“<”等非等于的比较也存在“==”的行为,并且没有像“===”的语法。
以下方法专注于一条“==”的推导逻辑,并不需要大量记忆,而且一些内容也有着一定的解释,相信大部分有经验的前端程序员都是通过大量经验或记忆来避免“==”的错误,不过在看完下面的内容后,你不再需要这么做。当然,最大受益者是初学者。
以下内容我希望在《You dont know JS》替换掉作者的“==”内容,已经提了issues,但是作者已经三天没有回复了(我看到一些短幅内容已经回复),也不知道看没看。
其实我想等《You dont know JS》的作者回复或者讨论以下再来发布的,太慢了,我已经迫不及待跟大家来讨论了,哈哈!
需要记忆的少量知识
我相信,这个量肯定要比标准的内容还有一些特殊情况要少的多得多。
注意:此处的others表示其它基础类型
左值(x) | 右值(y) | 隐式处理 |
---|---|---|
string | number | ToNumber(x) |
boolean | others | ToNumber(x) |
Object | !Object | Toprimitive(x) |
Toprimitive(Object)
先返回valueOf()的值,若返回的不是基础类型的值,
则返回toString()的值,若返回的不是基础类型的值,
则抛出异常。
需要注意特殊情况:
- String对象,上述的转换过程是反过来的。
- 如果定义了[Symbol.toPrimitive],则此方法优先于前面两个方法。
比较特殊的知识点
undefined==null //true
null和undefined单独出现与其他值进行比较不进行转换。
空值情况
Number("<空值或空值的组合>")===0 //true
什么是空值?
- (啥都没有)
- (Space空格)
- (空格的转义)
- (Tab缩进)
- \r
- \n
- \f
- \t
- 可能还有,我只知道这么多了
掌握以上知识点其实已经完全掌握在”==“的状况下的隐式转换了,接下来是一些解释。
上述内容的一些解释
为什么null和undefined与其他值比较不进行转换
大家如果了解原型链就会知道null在原型链的顶层,null是没有任何方法的,所以null是不可以进行隐式转换的;而其他的基础类型因为引擎去包装了一层对应的构造函数,所以挂载了toString或toNumber这样的方法,可以进行隐式转换。
undefined,大家见过undefined()这样的写法吗?没有,所以它也没有构造函数,没有挂载方法,不可以进行隐式转换。
为什么null和undefined双等号相等,三等号不相等
ECMA标准规定,这点没有规律可循。
下面让我们来利用上述内容推导结果
首先,要纠正一下思维,(==)指可以进行强制类型转换的等于比较,隐式转换只是在双方属于不同类型的时候才会触发,遇到相同类型会直接比较。并且隐式转换具有阶段性,一会我们马上就会遇到。
就从《You dont know JS》来几个特殊的,因为上面作者出版的版本内容上特殊情况没有解释为什么,至于结果,我就不写出来了,自己动手才是王道。
- “0” == false
左值 | 右值 | 解释 |
---|---|---|
“0” | false | 符合左值为其他基础类型,右值为boolean的情况,右值toNumber |
“0” | 0 | 符合左值为string,右值为number的情况,左值toNumber |
0 | 0 |
- false == []
左值 | 右值 | 解释 |
---|---|---|
false | [] | 符合左值为非对象,右值为对象的情况,右值toPrimitive,最终是通过toString |
false | “” | 符合左值为boolean,右值为其他基础类型的情况,左值toNumber |
0 | “” | 符合左值为number,右值为string的情况,右值toNumber,并且符合空值情况,转换为0 |
0 | 0 |
false == undefined
符合undefined单独和其他值比较。
以上内容同样适用于(<)和(>)
但是要注意(<=)和(>=),他在引擎中会被处理成不大于和不小于,如:
a<=b ---> !(a>b)
为什么要说这点?试着输出下面的例子你就明白了
var a= {b:1};
var b= {b:2};
console.log(a>b); //false
console.log(a==b); //false
console.log(a>=b); //true
最后
如果还有什么不理解、想和我交流、发现问题的请下方评论。