一段基于lodash之看不懂的代码

什么样的代码算是好代码?

读得懂的就是好代码,讲究一个可读性(其实是想掩饰我的菜而已,嘘。。),不过确实也要考虑代码设计,扩展性各方面。
事情的缘故源于项目中的一段代码,第一眼看,What the hell,这是啥!第二遍看,excuse me???第三第四遍,哦~有点理解了,第五遍,还是不懂。。下面上代码(由于项目原因,并非项目中真实代码片段)。

const index = _.findIndex(routes, _.curry(_.isEqual)(action.route))   

这是一段路由reducer中的代码,我当然知道findIndex用法,也当然知道返回的是一个index`。第一个参数是一个数组,但是第二个参数是什么鬼?
如果你一眼就看明白了,那就不用继续看下去了。。可否留个联系方式收我为徒(真心的)。
不理解的话,那就和我一样一步一步的来分析下吧。

  • 首先,findIndex方法,三个参数,第一个是个数组,第二个是个callback。第三个参数是fromIndex,从第几个开始查找,默认是0。第二个参数callback接收三个参数,第一个value,就是遍历到的当前元素,第二个是index,就是遍历时的index,第三个就是this,也就是当前遍历的数组本身。
  • 代码中的第一个参数传入了routes,没啥问题,一个路由数组。但是第二个参数就一大堆了,我们把他拿出来拆开看_.curry(_.isEqual)(action.route)
  • curry就不多说了,函数柯里化,不知道的可以看我上一篇文章。但是lodash的curry方法有点不一样。第一个参数接受一个fn,第二个参数是arity,由这个参数决定返回值是fn的结果,还是返回整个fn函数,默认等于第一个参数fn的参数个数。curry传入一个fn返回一个被curry化过的fn,此时在调用这个fn,如果参数传够原来的fn的参数,那么就返回一个fn的返回值。如果参数未传够,那将直接返回fn函数本身。

来看个例子就明白了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
_.curry(_.isEqual)
function (n,t){
/* [wrapped with _.curry] */
return Ft(n,t);
}
_.curry(_.isEqual)(1)
function (n,t){
/* [wrapped with _.curry & _.partial] */
return Ft(n,t);
}
_.curry(_.isEqual)(1)(2)
false
_.curry(_.isEqual)(1)(1)
true

所以刚好_.curry(_.isEqual)(action.route)返回的还是isEqual函数自身,isEqual接受两个参数(a,b),返回一个布尔值。抛开它的实现不说,其他内部最终肯定是return a === b类似这样。
回到findIndex的第二个参数,要的是个fn,正好_.curry(_.isEqual)(action.route)返回的是isEqual这个函数,而action.route恰恰带入函数的第一个参数a,那第二个参数?isEqual第二个参数b其实就是遍历routes时的每一项,isEqual的逻辑就成了return routes[i] === action.route,这样一来,就达到了我们的目的。

题外话,其实这段代码也可以写成下面这样:
const index = _.findIndex(routes, route => route === action.route)
但是放眼望去,第一种写法才是符合fp的编程思想,而且也成功装X,岂不快哉!

菜鸟学习笔记,如有不对,还希望高手指点。如有造成误解,还希望多多谅解。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。