我悟出权利原本就是不讲理的——甲由就是海米;也悟出要造反,心田必需壮大到足以蒙受任何效果才行。
——北岛《城门开》
本文为读 lodash 源码的第十篇,后续文章会更新到这个堆栈中,迎接 star:pocket-lodash
gitbook也会同步堆栈的更新,gitbook地点:pocket-lodash
作用与用法
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
挪用该函数,假如返回的效果为真值,则中断查找,返回索引。
运算符优先级
我们再往外看,看看 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源码剖析之自减的两种情势》。
参考
License
签名-非商业性运用-制止归纳 4.0 国际 (CC BY-NC-ND 4.0)
末了,一切文章都邑同步发送到微信民众号上,迎接关注,迎接提意见:
作者:对角另一面