lodash源碼分析之baseFindIndex中的運算符優先級

我悟出權力原本就是不講理的——蟑螂就是海米;也悟出要造反,心裏必須強大到足以承受任何後果才行。javascript

——北島《城門開》java

本文爲讀 lodash 源碼的第十篇,後續文章會更新到這個倉庫中,歡迎 star:pocket-lodashgit

gitbook也會同步倉庫的更新,gitbook地址:pocket-lodashgithub

做用與用法

baseFindIndex 是內部方法,其做用相似於ES6的 findIndex,查找符合條件的第一個元素的索引。數組

baseFindIndex 除了從前向後查找外,還能夠從後向前查找。微信

用法以下:函數

baseFindIndex([3,1,2], function(val, index, array) {
  return val > 1
}, 1) // 從前向後查找,從索引1開始查找,返回2
baseFindIndex([3,1,2], function(val, index, array) {
  return val > 1
}, 1, true) // 從後向前查找,從索引1開始查找,返回3

源碼分析

function baseFindIndex(array, predicate, fromIndex, fromRight) {
  const { length } = array
  let index = fromIndex + (fromRight ? 1 : -1)

  while ((fromRight ? index-- : ++index < length)) {
    if (predicate(array[index], index, array)) {
      return index
    }
  }
  return -1
}

這段代碼再次展現了 lodash 的特色,短小精悍!源碼分析

此次讀源碼咱們從裏往外看。優化

從代碼中很容易看到,predicate 是傳遞進來的函數,在 baseFindIndex 調用該函數,若是返回的結果爲真值,則停止查找,返回索引。code

運算符優先級

咱們再往外看,看看 while 的循環條件:

fromRight ? index-- : ++index < length

如今問題來了,這個三元表達式有兩種可能,一種是:

(fromRight ? index-- : ++index) < length

一種是:

fromRight ? index-- : (++index < length)

到底是那一種呢?這就要看運算符的優化級了,下面這個表是 MDN 上的截圖:

這個表將優化級劃分紅了20個級別,數字越大,優化級越高。

從表中能夠看到,比較運算符的優先級爲11,而三元表達式(條件運算符)的優化級爲4,所以能夠肯定比較運算符的優先級要比三元表達式的要高,循環條件其實等價於第二種寫法。

增減迷局

再往上看,能夠看到這句代碼:

let index = fromIndex + (fromRight ? 1 : -1)

在向後查找時, index 減小了1,而向前查找時,index 增長了1,爲何要這樣作呢?

再結合循環條件看下:

fromRight ? index-- : ++index < length

在向前查找時,使用的是 index-- 表達式的運算結果,向後查找時,使用的是 ++index < lenth 表達式的運算結果。

從上表中也能夠看出前綴自增比比較運算符的優化級要高。

前綴自增返回的是自增後的結果,而在循環條件中就要將索引 index 增長1,這樣會忽略掉第一個須要遍歷的元素,做爲補救,在開始遍歷前,須要將 index 減小1。

同理,在向前查找時,須要將索引增長1,由於在遍歷開始時就已經將索引減小1。

那又爲何向前查找時用的是後綴自減,而不是用前綴自減呢?

由於在向前查找時,最終要查找到數組索引 0 的位置,後綴自減返回的是自減前的數值,所以當 index1 時,自減後的 index0 ,可是在循環條件中依然拿 1 來進行判斷,因此使得索引 0 得以進入循環體。

關於前綴自增/減和後綴自增/減的區別能夠看《lodash源碼分析之自減的兩種形式》。

參考

  1. MDN:運算符優先級

License

署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)

最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:

做者:對角另外一面

相關文章
相關標籤/搜索