我悟出權力原本就是不講理的——蟑螂就是海米;也悟出要造反,心裏必須強大到足以承受任何後果才行。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
的位置,後綴自減返回的是自減前的數值,所以當 index
爲 1
時,自減後的 index
爲 0
,可是在循環條件中依然拿 1
來進行判斷,因此使得索引 0
得以進入循環體。
關於前綴自增/減和後綴自增/減的區別能夠看《lodash源碼分析之自減的兩種形式》。
署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)
最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:
做者:對角另外一面