摘要:是函数柯里化的函数。例子柯里化有个常见作用参数复用构建高阶函数延迟计算。是的,它其实就是柯里化的具体应用构建高阶函数。这个是我认为的中最有意思的方法。不过要注意最后的。这同样是用来组合高阶函数的一个方法。
最近在学习JS函数式编程相关的内容,于是详细的翻看了Lodash的文档,感到别有洞天。这里把自己对一些API的使用和看法做个笔记记录下。
Array _.head/_.last例子:
_.head([1, 2, 3]); // → 1 _.last([1, 2, 3]); // → 3
分别可以抽取数组第一个元素的值和最后一个元素的值。咋看之下觉得很无聊。但是跟下面两个结合起来就厉害。
_.tail/_.initial例子:
_.tail([1, 2, 3]); // → [2, 3] _.initial([1, 2, 3]); // → [1, 2]
也如字面描述一般容易理解的函数。但是结合上面的两个函数就产生很大能量。
首先看一个针对数组尾部特殊化处理的例子:
let names=["fred", "barney", "pebbles"]; _.initial(names).join(", ") + (_.size(names) > 1 ? ", & " : "") + _.last(names); // → "fred, barney, & pebbles"
怎么样比简单的写for+if else优雅很多吧。接着我们来看看递归求和:
function sum(arr){ return _.head(arr) ? ( _.head(arr) + sum( _.tail(arr) ) ) : 0; }
Tips
1)其实好像数组都可以表现为
[a, [b, [c .....]]]
然后再将其扁平化的结果。 是不是?所以结合这四个函数,很多数组遍历的操作都可以改写成递归的方式。虽然性能可能略差,但是可读性反而更强了(并非所有的递归都一定损耗性能,详细可以去了解下JIT优化)。
2)但是在ES6中,更推荐优先使用数组的解构。
_.zip例子:
_.zip(["fred", "barney"], [30, 40]); // → [["fred", 30], ["barney", 40]]
_.zip(*array) 将几个数组按照位置组成新的数组,返回数组列表。这个方法就有点像SQL里面select两个列的情况。对重组数据结构非常有帮助。
_.unzip既然lodash是个函数库,那有zip肯定也有他的逆运算unzip。这里就不举例了。unzip其实可以看作对ES6数组解构的补充,应用的场景也是十分相似的。
Collection _.map/_.reduce/_.filter这三个函数其实早就名声在外,就不举例了。列出来只是为了提醒,遍历集合可不仅仅只有_.each。任何时候都优先考虑这些函数。
_.every/_.some例子:
let users = [ { "user": "barney", "active": true }, { "user": "fred", "active": false } ]; _.every(users, { "user": "barney", "active": false }); // → false _.some(users, ["active", false]); // → true
什么?看不懂?
_.every => && _.some => ||
懂了吧。其实同样也算是对_.each的扩充。还有他们都有条件短路的优化哦。
Function _.curry是函数柯里化的函数。不要问我为什么不是库里化。什么是柯里化自行百度。
例子:
let abc = function(a, b, c) { return [a, b, c]; }; let curried = _.curry(abc); curried(1)(2)(3); // → [1, 2, 3] curried(1, 2)(3); // → [1, 2, 3] curried(1, 2, 3); // → [1, 2, 3] // Curried with placeholders. curried(1)(_, 3)(2); // → [1, 2, 3]
柯里化有3个常见作用:1. 参数复用;2. 构建高阶函数;3. 延迟计算。
参数复用的例子:
let parse = function(data, config){ …… return ……; }; let config = {}; let parseByConfig = _.curryRight(parse)(config);
如代码所示,这是一个数据解析函数,通过某些配置按照一定的规则去解析数据。如果在某个场景下参数配置都一样。那可以用柯里化先引入一个参数。然后再接收不同的数据。这样就不用在每次调用时都引入同样的config参数。
剩下两个特性一个等会讲,一个不在本文讨论范围内。
_.partial部分函数,我习惯这么叫他,还是先看例子。
let greet = function(greeting, name) { return greeting + " " + name; }; let sayHelloTo = _.partial(greet, "hello"); sayHelloTo("fred"); // → "hello fred" // Partially applied with placeholders. let greetFred = _.partial(greet, _, "fred"); greetFred("hi"); // → "hi fred" let greet = function(greeting, name) { return greeting + " " + name; }; let sayHelloTo = _.partial(greet, "hello"); sayHelloTo("fred"); // → "hello fred" // Partially applied with placeholders. let greetFred = _.partial(greet, _, "fred"); greetFred("hi"); // → "hi fred"
好像跟柯里化很像。是的,它其实就是柯里化的具体应用——构建高阶函数。_.curry会把一个函数转化成可以柯里化函数,而当这个柯里化函数接受了一定的参数后,它就变成了一个部分应用函数了。
Seq _.chain这个是我认为的lodash中最有意思的方法。
$("div").css("color","red") .on("click", function(){}) .fadeIn();
作为一个合格的前端攻城狮,你对这个一定不陌生。它一定给你带来过很多美好的记忆。那我们如何让这样一段优雅的代码应用到非DOM对象上呢。用_.chain就行了。
_.head( _.map( _.sortBy("users", "age"), function(o) { return `${o.user} is ${o.age}`; } ) ) _.chain(users) .sortBy("age") .map(function(o) { return o.user + " is " + o.age; }) .head() .value();
两段代码在做一样的事情。你更喜欢哪个呢。不过要注意_.chain最后的value。因为_.chain用一个容器包装了你的对象,最后需要通过value返回出真正的值。如果不能理解,联想一下下面这段代码:
$("div")[0].classList
用jQuery选择器筛选到的是jQuery对象,而如果要调用真正的DOM对象的属性的话,还要用索引去调用它。
Util _.flowfunction square(n) { return n * n; } var addSquare = _.flow(_.add, square); addSquare(1, 2); // → 9
这同样是用来组合高阶函数的一个方法。如果用数学的角度去思考的话,就有点像, 把函数 f(), g(), 和h() 组合起来可以得到复合函数 f( g( h() ) )。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/79387.html
摘要:例如现在的入门学习手记系列。收到粉丝留言和打赏的喜悦。安装上一篇入门学习手记一,主要是介绍了的核心概念,是整个学习过程的基础知识。新生成的类似如下入门学习手记因为生成的内容过多,我直接省略掉了。 showImg(https://segmentfault.com/img/bVbk5Nd?w=1150&h=599); 本人微信公众号:前端修炼之路,欢迎关注。 最近开始想要维护一个个人的公众...
摘要:中文文档目前我只找到了版本,现在已经更新到了,好多文档已经过期。而且中太多,有时候常用的几个我总是记不住名字,在这里贴出来,方便自己和大家。原生用法直接使用的根据条件去除某个元素。 lodash中文文档目前我只找到了3.10.x版本,现在lodash已经更新到4.17.x了,好多文档已经过期。而且lodash中api太多,有时候常用的几个我总是记不住名字,在这里贴出来,方便自己和大家。...
摘要:文档地址中文文档英文文档源码地址第一个函数是,不过源码中依赖了,所以第一篇文章就从开始。这个函数的作用就是裁剪数组,从下标开始,到下标结束,但是并不包含,并将结果作为一个数组返回。并且注明了这个方法用于代替来确保数组正确返回。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源...
摘要:文档地址中文文档英文文档源码地址将数组拆分成多个长度的区块,并将这些区块组成一个新数组。如果无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源码地址:gayhub _.chunk(array, [size...
摘要:文档地址中文文档英文文档源码地址创建一个新数组,包含原数组中所有的非假值元素。例如和都是被认为是假值。下面对比一下两者效率,如下图传送门可以看到使用更快,如果没有兼容性需求,还是使用原生函数比较好。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源码地址:gayhub ...
阅读 700·2021-11-23 09:51
阅读 2401·2021-10-11 11:10
阅读 1254·2021-09-23 11:21
阅读 1069·2021-09-10 10:50
阅读 857·2019-08-30 15:54
阅读 3293·2019-08-30 15:53
阅读 3271·2019-08-30 15:53
阅读 3168·2019-08-29 17:23