在没接触eslint以前,个人代码格式可谓是随着心情走的,爱怎么写就怎么写。自从三年前,作一个Vue项目引入了eslint
后,个人代码就变得规范多了,以致于如今还产生了强迫症。eslint
里面有不少代码规范的标准。通常状况下,React
项目代码遵循airbnb规范,Vue
项目代码遵循standard规范。不过里面都有一条细则说起:始终使用 === 替代 ==。就这样,我将这个习惯沿用到如今,但我并无去深究过,只知道这样作能减小代码中意想不到的出错。因为我本人并不甘心于“知其然而不知其因此然”,我想深究一番===
和==
的区别。javascript
===
和==
本质的区别是:前者是判断运算符两边的操做数是否严格等于,并不会作任何的数据类型转换;后者是判断运算符两边的操做数是否不严格等于,会适当地进行隐式类型转换。java
下面给出用==
运算符比较时,两边操做数x
与y
隐式类型转换的细则:git
1.x
与y
类型相同github
1.1 若x为undefined类型, 则返回true。ui
console.log(undefined == undefined); // true
复制代码
1.2 若x为null类型,则返回true。spa
console.log(null == null); // true
复制代码
1.3 若x为number类型,且x和y只要有一者为NaN,则返回false。(NaN并不等于自己)eslint
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。code
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
方法,再进行比较。
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
,利用上面罗列的细则,咱们一步步推导。
// ![]返回是一个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代码规范了。