幾天前在審查公司實習生代碼時查出一個bug,代碼是這樣寫的:3d
pic1cdn
他這裏的業務是先從接口中拿到某個對象的數據,若是這個對象爲空的話會將它賦值爲null,
若是對象有值作進一步處理,若是對象的str屬性不爲空再作某些處理。
固然,這裏作if判斷的話徹底沒有必要利用相等操做符, 直接經過數據自己判斷就能夠了即 對象
可是最開始的時候我只是以爲他的代碼不夠規範,不以爲他的寫法(pic1)有什麼邏輯上的影響,後來才發現這兩種寫法有着天差地別。pic1中的兩個if判斷都會永遠返回false。blog
首先咱們如今控制檯打幾個簡單的語句繼承
咱們能夠得出:接口
(結論1)將全部對象包括空對象轉成布爾值都會返回true(不包括null)。ip
(結論2)咱們都知道if語句條件判斷的括號中能夠放變量,也能夠放表達式。字符串
因此針對兩個案例中的第一個if判斷咱們能夠模擬出get
很明顯,第一個判斷返回值爲true,第二個if判斷返回值是false,原型
咱們來分析一下上邊這段代碼,
首先第一個判斷至關於Boolean(o),根據結論1,這個返回值必定是true。
第二個判斷會先計算o==true的結果,而後再將其轉換爲布爾值,可能有少部分同窗也會想固然的覺得這裏會先將o轉換爲布爾值,和等號右邊的類型相同後再做比較,
咱們能夠在控制檯打一下這個表達式:
若是是先將o轉成布爾值後再與true作比較的話,返回值必定爲true即:
可見他不是這樣轉換的,那麼它是怎樣轉換的呢?
我去查了一下紅寶書,是這樣規定的:
在執行相等運算符時,若是有一方類型爲布爾值,那麼會將布爾值轉換爲數字類型後再比較
那在咱們這個例子中布爾值true被轉換成1,那等號另外一端的對象是怎樣轉換的呢?因而我往下翻,還有這樣一條:
若是有一方爲對象,另外一方爲非對象,則執行對象的valueOf方法後獲得基本數據類型再做比較,若是得不到基本數據類型,再執行它得toString方法後進行比較。
那咱們先看一下咱們實例化的對象o繼承Object原型上默認定義的valueOf方法和toString()方法會返回什麼
因此咱們能夠猜測o==true判斷時經歷瞭如下幾個步驟:
爲了驗證咱們上邊的猜測,我在控制檯寫了如下代碼:
足以證實咱們的猜測步驟是正確的。
然而咱們案例中的第二個判斷字符串與布爾值比較也是將其先轉換成數值後再進行比較。
至關於:Number(o.str) === Number(true)
前者返回NaN,後者返回1,固然不等。
咱們上面的案例是解決了,可是其餘類型的相等運算符是怎樣轉換的呢?
我先提出兩個問題
1.你們都知道 null==undefined 返回的結果爲true,那麼它是怎樣進行類型轉換的呢?
2.null==0 undefined==0的返回值分別是多少?
不賣關子,直接說答案
第一個問題
不會進行類型轉換
誤區:有的同窗可能覺得null和undefined都會先轉換爲布爾值,而後再判斷相等性。
正確思路:其實他們的相等是js規定的,這裏不會進行類型轉換。
第二個問題
返回值都爲false
誤區:若是按照案例中的思路有些人可能會覺得null和undefined也是都會被轉換爲Number後再作判斷。
對undefined來說Number(undefined)返回值爲NaN,與0相比返回false很正常,
可是Number(null)的返回值爲0 爲何也與0相比返回false呢?
正確思路:其實這裏js規定Null和undefined與其餘數據類型比較時不會進行類型轉換,因此返回結果都爲false。
更多類型的相等運算符比較: