從isEmpty()方法深入理解javascript運算符優先級

前言

在平時的開發中,咱們常常會遇到多種運算符在同一個表達式中出現的狀況,尤爲是在三元條件判斷運算符中。javascript

三元條件判斷運算符雖然可讓咱們避免寫過多的if...else條件判斷,但多層三元運算符嵌套,其中又包含其餘不一樣優先級的運算符時,對於閱讀咱們代碼的人來講,簡直就是噩夢。java

今天咱們就結合一個現實中常常用到的工具函數 isEmpty() 的實現,來說解一下如何解讀複雜的運算符嵌套jquery

isEmpty

isEmpty 是 著名的 loadsh 庫提供的一個工具方法,被應用於斷定一個javascript 對象是否爲空對象。segmentfault

空對象

對於空對象,loadsh 是這麼解釋的:數組

若是【對象沒有本身的可枚舉字符串鍵控屬性】,則認爲它們是空的,
若是參數、對象、緩衝區、字符串或相似於jquery的集合等【相似數組的值的長度爲0】,則認爲它們爲空。
相似地,若是【映射和集合的大小爲0】,則認爲它們是空的

isEmpty的實現

isEmpty = function (val) {
    return !(!!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length : true : false);
}

解讀

運算符優先級

javascript 的運算符優先級能夠參考MDN上的說明,以下圖:框架

運算過程解讀

咱們再看內部實現代碼,其中val爲要判斷是否爲空對象的值:函數

return !(!!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length : true : false);

如今根據運算符優先級一步一步解讀運算過程工具

  1. 咱們知道 return 後面應該是一個表達式的值,咱們假定這個值爲X,則整個表達式能夠看作:
var X = !(...);
return X;
  1. 那麼接下來就要先對賦值符號(=)右邊的表達式求值,即:
!(...)
  1. 能夠看到,這個表達式有兩個運算符——邏輯非和括號,按照優先級,括號的優先級高於邏輯非,因此這裏邏輯非要等到括號內的內容運算出一個結果,而後才能對這個結果進行邏輯非運算,咱們假定括號內的內容最終運算的結果爲Y,則能夠寫做:
X = !Y
  1. 如今來看一下Y表達式的內容:
Y = !!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length :true :false
  1. 接下來就有點複雜了,按照優先級,按照這些運算符裏優先級最高的應該是成員屬性訪問(.),那應該第一步運算結果是這樣:
Y = !!val ? typeof val === 'object' ? (true/false) ? !!(0/1/2/.../N) : !!(0/1/2/.../N) :true :false

​ 由於咱們這裏對val的值不必定,因此這裏對 Array.isArray(val)Object.keys(val).length 最終的計算結果有多種可能,我用/號隔開了各類可能值,而且將他們放入同一個括號內,若是是正式的計算,咱們傳入的val是一個肯定的值,那麼這些運算結果也會是一個肯定值,而且也不會有括號。spa

  1. 接下來,邏輯非和typeof運算符的優先級都是16,是剩餘運算符中最高的,因此對這兩種進行運算,結果以下:
Y = (true/false) ? (string/object/boolean/null/undefined)==='object' ? (true/false) ? (true/false) : (true/false) : true :false

這個地方比較繞,由於!! 會將後面的值強制轉換爲布爾值,因此最後的結果幾乎都是由 truefalse 組成的了。code

  1. 接下來,整個表達式就只剩全等運算符(===)和三元條件運算符(... ? ... : ...)了, 從上表可知,全等運算符的優先級要高一點,因此結果以下:
Y = (true/false) ?(true/false) ? (true/false) ? (true/false) : (true/false) : true :false
  1. 如今,咱們的表達式裏就只剩三元條件運算符和布爾值了,問題是這裏有多個三元運算符嵌套,咱們該從哪一個開始計算呢? 如今就能夠看 結合性 了,咱們發現條件運算符的結合性是從右至左,那麼咱們的表達式就變成了:
Y = (true/false) ? ... : false

咱們回溯如下這裏面的 (true/false) 其實就是原始表達式中 !!val的運算結果,然而這裏還沒法運算出整個表達式的結果,由於 ... 所表明的那部分還不是一個最終值,還須要運算,記得最開始的作作法嗎?對於!(...)這個表達式,咱們將括號內的表達式用Y 來代替了,一樣地,咱們把這裏 ... 所表明的表達式部分用一個字母M 來表明,即:

M = (true/false) ? (true/false) ? (true/false) : (true/false) : true;
Y = (true/false) ? M : false;
  1. 到這裏,計算機就開始判斷了:

    • 若是!!val 的值爲false ,則直接返回 false (即括號後面的值),後面的M中的表達式就再也不運算了。那麼此時 Y=false, 而 !Y 至關於取反,X = !Y 的值就等於true 。咱們這個方法是用來判斷是否爲空對象的,返回結果爲true,就說明這個val 是空對象。
    • 咱們能夠延伸一下,符合 !!val === falseval 都有哪些呢? 0""false ,nullundefined 符合這個特徵,咱們發發現,它們都是javascript中的‘假值’。
    • 那麼若是!!val 的值爲 true呢,則須要返回M表達式的結果,咱們就須要繼續計算M表達式的值了。
  2. 如今咱們再看M表達式的運算過程,依葫蘆畫瓢,咱們能夠獲得:
M = (true/fasle) ? ... : true

經過回溯,咱們能夠知道,這裏的(true/false) 其實就是原始表達式中的typeof val === 'object' 的最終運算結果。

一樣的,咱們將 ... 內的內容使用字母 N 代替,結果以下:

N = (true/fasle) ? (true/fasle) : (true/false)
M = (true/false) ? N : true;
  1. 到這裏,計算機又開始判斷:

    • 若是typeof val === 'object' 的值爲false , 即說明val不是對象類型,則直接返回true(冒號後面的值),不須要再運算N表達式的結果。此時 Y = true, 則 X= !Y=false, 最終值爲false ,說明val 不是空對象。
    • 若是typeof val === 'object' 的值爲 true 則須要返回N表達式的值做爲結果,計算機須要計算運算N表達式的值。
  2. 對於N表達式,其中有三個布爾值,經過回溯,咱們也能夠知道他們的原始表達式分別是:
  • Array.isArray(val)
  • !!val.length
  • !!Object.keys(val).length

那麼咱們知道,這一步當val 爲對象類型時,則須要判斷它是數組仍是非數組:

  • 若是是數組,則拿到數組的長度值,對長度值作!!操做

    • 若是長度爲0 ,則操做結果爲false, 返回後,Y=false,X=!Y=true,說明 長度爲0的數組爲空對象
    • 其它長度結果爲 true,將結果返回後,Y=true, X=!Y=false,說明長度大於0的數組不屬於空對象
  • 若是不是數組,則取它的可枚舉屬性的長度(Object.keys(val).length),並對長度作!! 操做

    • 若是長度爲0 ,則操做結果爲false, 返回後,Y=false,X=!Y=true,說明 可枚舉屬性長度(個數)爲0的對象爲空對象
    • 其它長度結果爲 true,將結果返回後,Y=true, X=!Y=false,說明可枚舉屬性長度大於0的對象不屬於空對象

總結

至此,咱們按照程序執行的順序步進似的完成了整個運算過程的模擬,咱們學到了如下幾點:

  • 代換法。當表達式很是複雜時,能夠按照運算符優先級,使用變量代換法代換優先級比較低的運算,先將注意力集中到優先級比較高的運算上。
  • 回溯法。步進代換和運算到最後,再無可代換運算時,就要開始回溯,對應到原始表達式,一步步求解。
  • 結合性。之前咱們偏重運算符優先級的分析,從這個例子的條件運算符三層嵌套的應用,咱們看到,在複雜表達式的分析中,運算符的結合性也是很是重要的分辨運算順序的參照標準。

理解運算過程對咱們理解整個程序的實現邏輯和做者的思惟方式相當重要,但願以上分析過程能夠在你們閱讀知名框架中大神級代碼時對你們有所幫助。

本文由博客一文多發平臺 OpenWrite 發佈!
相關文章
相關標籤/搜索