在沒接觸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代碼規範了。