在 ES6 大行其道的今天,还有必要使用 lodash 之类的库吗?

reindexio/youmightnotneedunderscore · GitHub
关注者
344
被浏览
226,049
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

其实 lodash 或 ramda 之类的库,并不只是提供了一些数据处理的基础方法,同时还方便了我们以 Functional Programming 的思路来进行数据处理。对于习惯使用 ramda 的朋友来说,肯定已经很了解 Functional Programming 所带来的好处,但是很多使用 lodash 的朋友还是只把它当做一个 util 来使用。下面我用 lodash 具体说一下到底他提供了那些原生 ES6 没有的功能。

lodash/fp

首先我需要声明一点,我后面提到的所有方法都是 lodash/fp 下面的,关于他的具体介绍可以看这里:

FP Guide · lodash/lodash Wiki · GitHub

它是可以按需加载的,如果我只需要 map,那么我可以 import map from 'lodash/fp/map',它就只会引入 map 相关的代码。

Immutable

lodash/fp 下面的所有方法,都是 Immutable 的。就是说所有的方法都不会改变传入参数的原始对象,只会返回一个新的对象。

这样强制规定以后,就可以避免一不小心修改了原始对象造成了错误。而 JS 原生的 Array 方法,有一些是 mutable 的,有一些是 immutable 的,即使很熟悉的人也有可能一不注意就犯错了。我以前就在原生的 reverse 方法坑惨了,它竟然是 mutable 的。。。

Compose

lodash/fp 下面的所有方法,都是 Auto-curried Iteratee-first Data-last 处理过的。这三个形容词是什么意思呢?

Auto-curried:所有的方法都是柯理化的

Iteratee-first:处理过程(函数)作为第一个参数传入

Data-last:处理对象作为最后的参数传入

这三个处理在我的理解中,都是为了 compose 做准备的。什么是 compose 呢?下面可以看一个例子:

import toUpper from 'lodash/fp/toUpper';
import head from 'lodash/fp/head';
import flow from 'lodash/fp/flow';
import filter from 'lodash/fp/filter';

const names = ['liu', 'wang', 'chen'];

const toUpperHeadNames = flow(
  toUpper,
  head
);

const toUpperHeadNamesWithoutL flow(
  toUpperHeadNames,
  filter(letter => letter !== 'L')
);

console.log(toUpperHeadNames(names)) // ['L', 'W', 'C']
console.log(toUpperHeadNamesWithoutL(names)) // ['W', 'C']

在上面的例子中,我们使用了 lodash 提供的 compose 方法 flow,将两个基本函数组合成了我们所需要的数据处理函数,然后又把这个数据处理函数与另一个基础函数组合成了另一个数据处理函数。也就是说,我们可以通过 compose 对函数进行任意的组合,这样可以极大的增加函数的灵活性和复用性。这也是原生方法所不能提供的便利。

Lazy Evaluation

通过 flow 创建的函数是 lazy evaluation 的。lazy evaluation 的解释可以参考这里

Lazy evaluation

。简单来说,就是当处理过程复杂的情况下,lazy evaluation 可以让计算性能提高非常多。flow 已经自带做了这种性能优化,而原生的链式调用是不会有这种性能优化的。