lodash源码分析之baseFindIndex中的运算符优先级
我悟出权力本来就是不讲理的——蟑螂就是海米;也悟出要造反,内心必须强大到足以承受任何后果才行。
——北岛《城门开》
本文为读 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)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见: 
作者:对角另一面
lodash源码分析之baseFindIndex中的运算符优先级的更多相关文章
- lodash源码分析之compact中的遍历
小时候, 乡愁是一枚小小的邮票, 我在这头, 母亲在那头. 长大后,乡愁是一张窄窄的船票, 我在这头, 新娘在那头. 后来啊, 乡愁是一方矮矮的坟墓, 我在外头, 母亲在里头. 而现在, 乡愁是一湾浅 ...
- lodash源码分析之自减的两种形式
这个世界需要一个特定的恶人,可以供人们指名道姓,千夫所指:"全都怪你". --村上春树<当我谈跑步时我谈些什么> 本文为读 lodash 源码的第六篇,后续文章会更新到 ...
- lodash源码分析之List缓存
昨日我沿着河岸/漫步到/芦苇弯腰喝水的地方 顺便请烟囱/在天空为我写一封长长的信 潦是潦草了些/而我的心意/则明亮亦如你窗前的烛光/稍有暧昧之处/势所难免/因为风的缘故 --洛夫<因为风的缘故& ...
- lodash源码分析之缓存方式的选择
每个人心里都有一团火,路过的人只看到烟. --<至爱梵高·星空之谜> 本文为读 lodash 源码的第八篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash gitb ...
- lodash源码分析之缓存使用方式的进一步封装
在世界上所有的民族之中,支配着他们的喜怒选择的并不是天性,而是他们的观点. --卢梭<社会与契约论> 本文为读 lodash 源码的第九篇,后续文章会更新到这个仓库中,欢迎 star:po ...
- lodash源码分析之数组的差集
外部世界那些破旧与贫困的样子,可以使我内心世界得到平衡. --卡尔维诺<烟云> 本文为读 lodash 源码的第十七篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodas ...
- angular源码分析:angular中脏活累活的承担者之$interpolate
一.首先抛出两个问题 问题一:在angular中我们绑定数据最基本的方式是用两个大括号将$scope的变量包裹起来,那么如果想将大括号换成其他什么符号,比如换成[{与}],可不可以呢,如果可以在哪里配 ...
- angular源码分析:angular中入境检察官$sce
一.ng-bing-html指令问题 需求:我需要将一个变量$scope.x = '<a href="http://www.cnblogs.com/web2-developer/&qu ...
- angular源码分析:angular中各种常用函数,比较省代码的各种小技巧
angular的工具函数 在angular的API文档中,在最前面就是讲的就是angular的工具函数,下面列出来 angular.bind //用户将函数和对象绑定在一起,返回一个新的函数 angu ...
随机推荐
- my discipline life
周一 ~ 周五 7.30 --- 8.00 起床,洗漱等 8.00 --- 8.30 默写8-10个英语单词 8.35 --- 9.10 吃早餐,骑自行车去公司 12.20 --- 1 ...
- [搬运] 写给 C# 开发人员的函数式编程
原文地址:http://www.dotnetcurry.com/csharp/1384/functional-programming-fsharp-for-csharp-developers 摘要:作 ...
- Zabbix实战-简易教程--技巧一(操作类技巧)
一.常用操作技巧 1.克隆 监控项.模板.触发器都可以进行克隆.其中,模板克隆又分为克隆和完全克隆.完全克隆会将LLD也一起复制一份,就是和之前的模板一模一样,而模板的克隆只是克隆监控项,不复制低层次 ...
- iOS学习——iOS项目Project 和 Targets配置详解
最近开始学习完整iOS项目的开发流程和思路,在实际的项目开发过程中,我们通常需要对项目代码和资料进行版本控制和管理,一般比较常用的SVN或者Github进行代码版本控制和项目管理.我们iOS项目的开发 ...
- bzoj:2331: [SCOI2011]地板
Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板.现在小L想知道,用 ...
- hihoCoder #1053 : 居民迁移(贪心,二分搜索,google在线技术笔试模拟)
#1053 : 居民迁移 时间限制:3000ms 单点时限:1000ms 内存限制:256MB 描述 公元2411年,人类开始在地球以外的行星建立居住点.在第1326号殖民星上,N个居住点分布在一条直 ...
- hbmy周赛1--D
D - Toy Cars Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submi ...
- [国嵌攻略][052][NandFlash驱动设计_读]
NandFlash读数据方式 1.页读,读出页中主数据区的所有数据,提供页地址(行地址) 2.随机读,读出页中指定的存储单元的数据,提供页地址(行地址)和页内偏移(行地址) 代码编写 1.根据Nand ...
- Winform & Devexpress Chart使用入门
一.Chart(Winform) 使用图表控件(chart)首先要理解图表区域(ChartArea).XY轴(AxisX.AxisY).数据点(Series).标题(Title).图例(Legend) ...
- c++---天梯赛---N个数求和
★题目: ★难点:要求只能以有理数和分数去输出结果. ★分析:可以对输入的数据进行通分处理,随后把结果按格式输出. ★代码: #include<iostream> #include< ...