Open Checkson opened 5 years ago
在没接触eslint之前,我的代码格式可谓是随着心情走的,爱怎么写就怎么写。自从三年前,做一个Vue项目引入了eslint后,我的代码就变得规范多了,以至于现在还产生了强迫症。eslint里面有很多代码规范的标准。一般情况下,React项目代码遵循airbnb规范,Vue项目代码遵循standard规范。不过里面都有一条细则提及:始终使用 === 替代 ==。就这样,我将这个习惯沿用到现在,但我并没有去深究过,只知道这样做能减少代码中意想不到的出错。由于我本人并不甘心于“知其然而不知其所以然”,我想深究一番===和==的区别。
eslint
React
Vue
===
==
===和==本质的区别是:前者是判断运算符两边的操作数是否严格等于,并不会做任何的数据类型转换;后者是判断运算符两边的操作数是否不严格等于,会适当地进行隐式类型转换。
下面给出用==运算符比较时,两边操作数x与y隐式类型转换的细则:
x
y
1.x与y类型相同
1.1 若x为undefined类型, 则返回true。
console.log(undefined == undefined); // true
1.2 若x为null类型,则返回true。
console.log(null == null); // true
1.3 若x为number类型,且x和y只要有一者为NaN,则返回false。(NaN并不等于本身)
console.log(NaN == 0); // false console.log(0 == NaN); // false console.log(NaN == 1); // false console.log(1 == NaN); // false console.log(NaN == NaN); // false
1.4 若x为number类型,且x和y的数值相等,则返回true。若x和y的数值不相等,则返回false。
console.log(0 == 0); // true console.log(1 == 1); // true console.log(0 == 1); // false
1.5 若x为number类型,且x和y的值为+0或者-0,则返回true。
console.log(-0 == +0); // true console.log(+0 == -0); // true console.log(+0 == +0); // true console.log(-0 == -0); // true
1.6 若x为string类型,当且仅当x和y字符序列完全相等的,则返回true。否则,返回false。
console.log('foo' == 'foo'); //true console.log('foo' == 'bar'); // false
1.7 若x为boolean类型,当x和y二者同为true或者false时,则返回true。否则,返回false。
console.log(true == true); // true console.log(false == false); // true console.log(true == false); // false console.log(false == true); // false
1.8 若x为object类型,当且仅当x和y二者是同一引用,则返回true。否则,返回false。
var x = {}, y = {}, z = x; console.log(x == y); // false console.log(x == z); // true console.log(y == z); // false console.log(x == {}); // false console.log({} == y); // false console.log({} == {}); // false
2.x与y类型不相同
2.1 若x为null,y为undefined,或者x为undefined,y为null,则返回true。
console.log(null == undefined); // true console.log(undefined == null); // true
2.2 若x与y二者,一个为number类型,另一个为string类型,则先将string类型隐式转换为number类型,再进行数值比较。
console.log('123' == 123); // true <=> Number('123') == 123 <=> 123 == 123 console.log(123 == '123'); // true <=> 123 == Number('123') <=> 123 == 123 console.log('abc' == 123) // false <=> Number('abc') == 123 <=> NaN == 123
2.3 若x与y二者,若存在一个为boolean类型,则先将boolean类型隐式转换为number类型,再进行数值比较。
console.log(false == 0); // true <=> Number(false) == 0 <=> 0 == 0 console.log(true == 1); // true <=> Number(true) == 1 <=> 1 == 1 console.log(false == 2); // false <=> Number(false) == 2 <=> 0 == 2 console.log(true == 2); // false <=> Number(true) == 2 <=> 1 == 2
2.4 若x与y二者,一个为number类型或者string类型或者boolean类型,另一个为object类型时,object类型会隐式调用valueOf或者toString方法,再进行比较。
valueOf
toString
var foo = { bar: 0 }; console.log(foo == 2); // false <=> foo.toString() == 2 <=> '[object Object]' == 2 <=> Number('[object Object]') == 2 <=> NaN == 2 console.log(foo == '2'); // false <=> foo.toString() == '2' <=> '[object Object]' == '2' console.log(foo == '[object Object]'); // true
ps:我们可以重写valueOf或者toString方法来覆盖原生方法默认的行为,来达到最佳的对比效果。
var foo = { bar: 0 }; foo.toString = () => '2'; // foo.valueOf = () => 2; 若两者都重写了,以valueOf为准 console.log(foo == 2); // true; console.log(foo == '2'); // true
2.5 其余情况返回false。
console.log('123abc' == 123); // false console.log(null == false); // false console.log(undefined == false); // false ...
接着,我们探讨一下一个有趣的题目:[] == ![] // -> true,利用上面罗列的细则,我们一步步推导。
[] == ![] // -> true
// ![]返回是一个boolean类型 -> !Boolean([]) -> !true -> false [] == ![] <=> [] == false // object类型和boolean对比,先转换对象 -> [] -> [].toString() -> '' [] == false <=> '' == false // ==两边操作数出现boolean类型,我们先将它做数字类型转换 -> false -> Number(false) -> 0 '' == false <=> '' == 0 // ==两边操作数出现string类型和number类型,我们先将string类型做数字类型转换 -> '' -> Number('') -> 0 '' == 0 <=> 0 == 0 // 所以最后得出的结果为 true。
可见,这些细则已经足够难记,倘若某一天我们还没去注意怎么使用==,程序中难免会出现很多意想不到的bug。为了尽量避免出错,我实际开发中,一般只会使用===,而不会使用==。
接下来,我们看看,使用===的细则,这里同样用x和y代表运算符两边的操作数。
console.log(undefined === null); // false console.log(1 === true); // false console.log(0 === false); // false console.log(1 === '1'); // false console.log(0 === '0'); // false console.log('1' === true); // false console.log('0' === false); // false console.log(0 === []); // false console.log(false === []); // false console.log('' === []); // false
var a = {}, b = {}, c = a; console.log(undefined === undefined); // true console.log(null === null); // true console.log(0 === 0); // true console.log(0 === 1); // false console.log('0' === '0'); // true console.log('0' === '1'); false console.log(false === false); // true; console.log(true === false); // false console.log({} === {}); // false console.log(a === b); // false console.log(a === c); // true; console.log(b === c); // false ...
我们可以看到,使用===仅有两条细则,完全不涉及到一些隐式数据类型转换,大大提高了代码的可调试性和可预见性,而且易用性远比==好。所以,在日常开发中,我强烈推荐使用===,尽可能少用==。或许我的推荐显得不怎么权威,但是,这个细则已经写入了很多JavaScript代码规范了。
前言
在没接触eslint之前,我的代码格式可谓是随着心情走的,爱怎么写就怎么写。自从三年前,做一个Vue项目引入了
eslint
后,我的代码就变得规范多了,以至于现在还产生了强迫症。eslint
里面有很多代码规范的标准。一般情况下,React
项目代码遵循airbnb规范,Vue
项目代码遵循standard规范。不过里面都有一条细则提及:始终使用 === 替代 ==。就这样,我将这个习惯沿用到现在,但我并没有去深究过,只知道这样做能减少代码中意想不到的出错。由于我本人并不甘心于“知其然而不知其所以然”,我想深究一番===
和==
的区别。===和==的区别
===
和==
本质的区别是:前者是判断运算符两边的操作数是否严格等于,并不会做任何的数据类型转换;后者是判断运算符两边的操作数是否不严格等于,会适当地进行隐式类型转换。== 使用细则
下面给出用
==
运算符比较时,两边操作数x
与y
隐式类型转换的细则:1.
x
与y
类型相同1.1 若x为undefined类型, 则返回true。
1.2 若x为null类型,则返回true。
1.3 若x为number类型,且x和y只要有一者为NaN,则返回false。(NaN并不等于本身)
1.4 若x为number类型,且x和y的数值相等,则返回true。若x和y的数值不相等,则返回false。
1.5 若x为number类型,且x和y的值为+0或者-0,则返回true。
1.6 若x为string类型,当且仅当x和y字符序列完全相等的,则返回true。否则,返回false。
1.7 若x为boolean类型,当x和y二者同为true或者false时,则返回true。否则,返回false。
1.8 若x为object类型,当且仅当x和y二者是同一引用,则返回true。否则,返回false。
2.
x
与y
类型不相同2.1 若x为null,y为undefined,或者x为undefined,y为null,则返回true。
2.2 若x与y二者,一个为number类型,另一个为string类型,则先将string类型隐式转换为number类型,再进行数值比较。
2.3 若x与y二者,若存在一个为boolean类型,则先将boolean类型隐式转换为number类型,再进行数值比较。
2.4 若x与y二者,一个为number类型或者string类型或者boolean类型,另一个为object类型时,object类型会隐式调用
valueOf
或者toString
方法,再进行比较。2.5 其余情况返回false。
接着,我们探讨一下一个有趣的题目:
[] == ![] // -> true
,利用上面罗列的细则,我们一步步推导。可见,这些细则已经足够难记,倘若某一天我们还没去注意怎么使用
==
,程序中难免会出现很多意想不到的bug。为了尽量避免出错,我实际开发中,一般只会使用===
,而不会使用==
。=== 使用细则
接下来,我们看看,使用
===
的细则,这里同样用x和y代表运算符两边的操作数。我们可以看到,使用
===
仅有两条细则,完全不涉及到一些隐式数据类型转换,大大提高了代码的可调试性和可预见性,而且易用性远比==
好。所以,在日常开发中,我强烈推荐使用===
,尽可能少用==
。或许我的推荐显得不怎么权威,但是,这个细则已经写入了很多JavaScript代码规范了。