Lodash 内部封装了诸多对字符串、数组、对象等常见数据类型的处理函数,其中部分是目前 ECMAScript 尚未制定的规范,但同时被业界所认可的辅助函数。
模块组成
Lodash 提供的辅助函数主要分为以下几类,函数列表和用法实例请查看 Lodash 的官方文档:
- Array,适用于数组类型,比如填充数据、查找元素、数组分片等操作
- Collection,适用于数组和对象类型,部分适用于字符串,比如分组、查找、过滤等操作
- Function,适用于函数类型,比如节流、延迟、缓存、设置钩子等操作
- Lang,普遍适用于各种类型,常用于执行类型判断和类型转换
- Math,适用于数值类型,常用于执行数学运算
- Number,适用于生成随机数,比较数值与数值区间的关系
- Object,适用于对象类型,常用于对象的创建、扩展、类型转换、检索、集合等操作
- Seq,常用于创建链式调用,提高执行性能(惰性计算)
- String,适用于字符串类型
lodash/fp
lodash/fp 模块提供了更接近函数式编程的开发方式,其内部的函数经过包装,具有 immutable、auto-curried、iteratee-first、data-last(官方介绍)等特点。Lodash 在 GitHub Wiki 中对 lodash/fp 的特点做了如下概述:
- Fixed Arity,固化参数个数,便于柯里化
- Rearragned Arguments,重新调整参数位置,便于函数之间的聚合
- Capped Iteratee Argument,封装 Iteratee 参数
- New Methods
|
|
在 React + Webpack + Babel(ES6) 的开发环境中,使用 Lodash 需要安装插件 babel-plugin-lodash 并更新 Babel 配置文件:
|
|
更新 Babel 的配置文件 .babelrc:
|
|
使用方式:
|
|
性能
在 Filip Zawada 的文章《How to Speed Up Lo-Dash ×100? Introducing Lazy Evaluation》 中提到了 Lodash 提高执行速度的思路,主要有三点:Lazy Evaluation、Pipelining 和 Deferred Execution。下面两张图来自 Filip 的博客:
假设有如上图所示的问题:从若干个球中取出三个面值小于 10 的球。第一步是从所有的球中取出所有面值小于 10 的球,第二步是从上一步的结果取三个球。
上图是另一种解决方案,如果一个球能够通过第一步,那么就继续执行第二步,直至结束然后测试下一个球……当我们取到三个球之后就中断整个循环。Filip 称这是 Lazy Evaluation Algorithm,就个人理解这并不全面,他后续提到的 Pipelining(管道计算),再加上一个中断循环执行的算法应该更符合这里的图示。
此外,使用 Lodash 的链式调用时,只有显示或隐式调用 .value 方法才会对链式调用的整个操作进行取值,这种不在声明时立即求值,而在使用时求值的方式,是 Lazy Evaluation 最大的特点。
九个实例
受益于 Lodash 的普及程度,使用它可以提高多人开发时阅读代码的效率,减少彼此之间的误解(Loss of Consciousness)。在《Lodash: 10 Javascript Utility Functions That You Should Probably Stop Rewriting》一文中,作者列举了多个常用的 Lodash 函数,实例演示了使用 Lodash 的技巧。
1. N 次循环
|
|
for 语句是执行循环的不二选择,Array.apply 也可以模拟循环,但在上面代码的使用场景下,_.times() 的解决方式更加简洁和易于理解。
2. 深层查找属性值
|
|
_.map 方法是对原生 map 方法的改进,其中使用 pets[0].name 字符串对嵌套数据取值的方式简化了很多冗余的代码,非常类似使用 jQuery 选择 DOM 节点 ul > li > a,对于前端开发者来说有种久违的亲切感。
3. 个性化数组
|
|
在上面的代码中,我们要创建一个初始值不同、长度为 6 的数组,其中 _.uniqueId 方法用于生成独一无二的标识符(递增的数字,在程序运行期间保持独一无二),_partial 方法是对 bind 的封装。
4. 深拷贝
|
|
JavaScript 没有直接提供深拷贝的函数,但我们可以用其他函数来模拟,比如 JSON.parse(JSON.stringify(objectToClone)),但这种方法要求对象中的属性值不能是函数。Lodash 中的 _.cloneDeep 函数封装了深拷贝的逻辑,用起来更加简洁。
5. 随机数
|
|
Lodash 的随机数生成函数更贴近实际开发,ECMAScript 的随机数生成函数是底层必备的接口,两者都不可或缺。此外,使用 _.random(15, 20, true) 还可以在 15 到 20 之间生成随机的浮点数。
6. 对象扩展
|
|
_.assign 是浅拷贝,和 ES6 新增的 Ojbect.assign 函数功能一致(建议优先使用 Object.assign)。
7. 筛选属性
|
|
大多数情况下,Lodash 所提供的辅助函数都会比原生的函数更贴近开发需求。在上面的代码中,开发者可以使用数组、字符串以及函数的方式筛选对象的属性,并且最终会返回一个新的对象,中间执行筛选时不会对旧对象产生影响。
|
|
.pick 是 .omit 的相反操作,用于从其他对象中挑选属性生成新的对象。
8. 随机元素
|
|
_.sample 支持随机挑选多个元素并返回心的数组。
9. 针对 JSON.parse 的错误处理
|
|
如果你在使用 JSON.parse 时没有预置错误处理,那么它很有可能会成为一个定时炸弹,我们不应该默认接收的 JSON 对象都是有效的。try-catch 是最常见的错误处理方式,如果项目中 Lodash,那么可以使用 _.attmpt 替代 try-catch 的方式,当解析 JSON 出错时,该方法会返回一个 Error 对象。
随着 ES6 的普及,Lodash 的功能或多或少会被原生功能所替代,所以使用时还需要进一步甄别,建议优先使用原生函数,有关 ES6 替代 Lodash 的部分,请参考文章《10 Lodash Features You Can Replace with ES6》(中文版《10 个可用 ES6 替代的 Lodash 特性》)。
其中有两处非常值得一看:
|
|
在 ES6 中,如果一个函数只接收一个形参且函数体是一个 return 语句,就可以使用箭头函数简化为:
|
|
当有多重嵌套时,可以简化为:
|
|
参考资料
- Lodash 官方文档
- Lodash FP Guide
- babel-plugin-lodash
- How to Speed Up Lo-Dash ×100? Introducing Lazy Evaluation
- Lodash: 10 Javascript Utility Functions That You Should Probably Stop Rewriting
- 10 Lodash Features You Can Replace with ES6
Reprinted Articles
Author:pinggod
Link:https://www.jianshu.com/p/7436e40ac5d1