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

前言

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

相關文章
相關標籤/搜索