为何我只用===而不用==呢?

前言

在没接触eslint以前,个人代码格式可谓是随着心情走的,爱怎么写就怎么写。自从三年前,作一个Vue项目引入了eslint后,个人代码就变得规范多了,以致于如今还产生了强迫症。eslint里面有不少代码规范的标准。通常状况下,React项目代码遵循airbnb规范,Vue项目代码遵循standard规范。不过里面都有一条细则说起:始终使用 === 替代 ==。就这样,我将这个习惯沿用到如今,但我并无去深究过,只知道这样作能减小代码中意想不到的出错。因为我本人并不甘心于“知其然而不知其因此然”,我想深究一番=====的区别。javascript

===和==的区别

=====本质的区别是:前者是判断运算符两边的操做数是否严格等于,并不会作任何的数据类型转换;后者是判断运算符两边的操做数是否不严格等于,会适当地进行隐式类型转换。java

== 使用细则

下面给出用==运算符比较时,两边操做数xy隐式类型转换的细则:git

1.xy类型相同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.xy类型不相同

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表明运算符两边的操做数。

  • 若x和y类型不一样,直接返回false。
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
复制代码
  • 若x和y类型相同,若都为基本类型,对比两者数值是否相等;若为引用类型,对比二者引用地址是不是同一地址。
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代码规范了。

相关文章
相关标签/搜索