最好不要在 JS 中使用 ==!
最好不要在 JS 中使用 ==!
最好不要在 JS 中使用 ==!
不信?请看下面题目:
[[] == false, ['0'] == false, [1] == true, ['2'] == true, [[['3']]] == 3 ]
运行结果如下:
[true, true, true, false, true]
如果你一眼就能准确的看出上述代码的返回结果,那就当我没说。
如果不能,那我们还是最好不要使用 == 了吧。
看似很诡异,其实 == 是有自己的比较规则的,其规则如下:
抽象相等比较算法
以
x和y为值进行x == y比较会产生的结果可为true或false。比较的执行步骤如下:
- 若 Type(
x) 与 Type(y) 相同, 则:
- 若 Type(
x) 为 Undefined, 返回true;- 若 Type(
x) 为 Null, 返回true;- 若 Type(
x) 为 Number,则:
- 若
x为NaN,返回false;- 若
y为NaN,返回false;- 若
x与y为相等数值,返回true;- 若
x为+0且y为−0,返回true;- 若
x为−0且y为+0,返回true;- 返回
false;- 若 Type(
x) 为 String,则当x和y为完全相同的字符序列(长度相等且相同字符在相同位置)时返回true,否则,返回false;- 若 Type(
x) 为 Boolean,当x和y同为true或者同为false时返回true,否则,返回false;- 当
x和y为引用同一对象时返回true,否则,返回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;
问题解析
根据规则,我们来分析一下问题。以 [] == false 为例,他的比较过程应该是这样的:
[] == false=[根据第 7 条]=>[] == Number(false)=[] == 0=[根据第 9 条]=>Number([].toString()) == 0=Number('') == 0=0 == 0=[根据第 1.3.3 条]=>- 返回
true
他们都转成了数字,想不到吧。
规则总结
总体来说,== 比较分为 2 种情况:需要类型转换的和不需要类型转换的。
不需要类型转换的比较
这类主要靠记忆,总结如下:
null == undefined返回 true;NaN和任何东西都不相等,包括他自己;0在比较的时候不分正负,即:+0等于-0;- 类型相同的比较,就不说了;
注意:null 和 undefined 在 === 下不成立。
需要类型转换的比较
需要类型转换的前提是比较的双方类型不相同。
boolean类型转成number类型;- 和
number类型比较都转number,对象先调一下toString再转number; - 如果和
string类型比较(比较对象不是number),转一下字符串;
与 === 对比
是不是比较麻烦,我有一个好办法,那就是不要用 ==,使用 ===!
严格等于(===)比较算法如下:
比较
x===y,x和y为值,需要产出true或false。比较过程如下:
- 如果 Type(
x) 与 Type(y) 的结果不一致,返回false;- 如果 Type(
x) 结果为 Undefined,返回true;- 如果 Type(
x) 结果为 Null,返回true;- 如果 Type(
x) 结果为 Number,则:
- 如果
x为 NaN,返回false;- 如果
y为 NaN,返回false;- 如果
x与y为同一个数字,返回true;- 如果
x为+0,y为-0,返回true;- 如果
x为-0,y为+0,返回true;- 返回
false;- 如果 Type(
x) 结果为 String,如果x与y为完全相同的字符序列(相同的长度和相同的字符对应相同的位置),返回true,否则,返回false;- 如果 Type(
x) 结果为 Boolean,如果x与y都为true或false,则返回true,否则,返回false;- 如果
x和y引用到同一个 Object 对象,返回true,否则,返回false。
=== 简单直接,对于不同类型直接返回 false,节省了类型转换的时间。