资讯专栏INFORMATION COLUMN

lodash源码分析之baseFindIndex中的运算符优先级

Meathill / 802人阅读

摘要:从表中可以看到,比较运算符的优先级为,而三元表达式条件运算符的优化级为,因此可以确定比较运算符的优先级要比三元表达式的要高,循环条件其实等价于第二种写法。从上表中也可以看出前缀自增比比较运算符的优化级要高。

我悟出权力本来就是不讲理的——蟑螂就是海米;也悟出要造反,内心必须强大到足以承受任何后果才行。

——北岛《城门开》

本文为读 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 的位置,后缀自减返回的是自减前的数值,因此当 index1 时,自减后的 index0 ,但是在循环条件中依然拿 1 来进行判断,所以使得索引 0 得以进入循环体。

关于前缀自增/减和后缀自增/减的区别可以看《lodash源码分析之自减的两种形式》。

参考

MDN:运算符优先级

License

署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)

最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:

作者:对角另一面

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107254.html

相关文章

  • lodash源码分析缓存方式的选择

    摘要:接口设计同样实现了跟一致的数据管理接口,如下依赖源码分析之缓存源码分析之缓存源码分析是否使用这个函数用来判断是否使用缓存。返回表示使用缓存,返回则使用或者缓存。获取对应缓存方式的实例这个函数根据来获取储存了该的缓存实例。 每个人心里都有一团火,路过的人只看到烟。——《至爱梵高·星空之谜》 本文为读 lodash 源码的第八篇,后续文章会更新到这个仓库中,欢迎 star:pocket-...

    HitenDev 评论0 收藏0
  • lodash源码分析缓存方式的选择

    摘要:接口设计同样实现了跟一致的数据管理接口,如下依赖源码分析之缓存源码分析之缓存源码分析是否使用这个函数用来判断是否使用缓存。返回表示使用缓存,返回则使用或者缓存。获取对应缓存方式的实例这个函数根据来获取储存了该的缓存实例。 每个人心里都有一团火,路过的人只看到烟。——《至爱梵高·星空之谜》 本文为读 lodash 源码的第八篇,后续文章会更新到这个仓库中,欢迎 star:pocket-...

    AdolphLWQ 评论0 收藏0
  • lodash源码分析数组的差集

    摘要:依赖源码分析之缓存使用方式的进一步封装源码分析之源码分析之源码分析之的实现源码分析之源码分析的调用如果有传递,则先调用,使用生成要比较数组的映射数组。循环完毕,没有在第二个数组中发现相同的项时,将该项存入数组中。 外部世界那些破旧与贫困的样子,可以使我内心世界得到平衡。——卡尔维诺《烟云》 本文为读 lodash 源码的第十七篇,后续文章会更新到这个仓库中,欢迎 star:pocke...

    Noodles 评论0 收藏0
  • lodash源码分析自减的两种形式

    摘要:作用与用法是的内部函数,之前在源码分析之缓存介绍过一种这样的数据结构这是一个二维数组,每项中的第一项作为缓存对象的,第二项为缓存的值。 这个世界需要一个特定的恶人,可以供人们指名道姓,千夫所指:全都怪你。——村上春树《当我谈跑步时我谈些什么》 本文为读 lodash 源码的第六篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash gitbook也会同步仓库的更新...

    Keven 评论0 收藏0
  • lodash源码从slice看稀疏数组与密集数组

    摘要:例如其中的为,但是数组中没有元素,是稀疏数组而每个位置都是有元素的,虽然每个元素都为,为密集数组。那稀疏数组和密集数组有什么区别呢在中最主要考虑的是两者在迭代器中的表现。截取并返回新数组为新数组容器。 卑鄙是卑鄙者的通行证,高尚是高尚者的墓志铭。 ——北岛《回答》 看北岛就是从这两句诗开始的,高尚者已死,只剩卑鄙者在世间横行。 本文为读 lodash 源码的第一篇,后续文章会更新到...

    lijy91 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<