你如何使用 lodash 链接函数?

How do you chain functions using lodash?

我有一个对象看起来像

var foundUser = {
    charData: []
}

然后我使用 mysql 从数据库加载一个对象,然后我调用

_.assignIn(foundUser, rows[0]);

但是我得到了一些我不需要的额外属性(这无法通过使用 select 解决)

所以我打电话给

foundUser = _.omit(foundUser, ['blah']);

但如果我能做到就好了

_.assignIn(foundUser, rows[0]).omit(rows[0], ['blah']);

但这会引发错误,是我做错了还是有其他方法可以做到这一点?

要使用 lodash 链接,首先必须包装对象:

_(foundUser).assignIn(rows[0]).omit(['blah']).value();

进一步说明:

_ 创建了一个允许隐式方法链接的 lodash 对象。隐式方法链接意味着在某些情况下它可能 return 一个原始值,在其他情况下它可能 return 一个 lodash 对象,您需要通过对其调用 .value() 来解包。

如果您使用 _.chain(...),您将创建一个带有显式方法链接的 lodash 对象。结果始终是一个包装值,并且始终需要通过对其调用 .value() 来解包。

如需进一步参考,请访问此处的文档链接:

Explicit chaining in Lodash

Implicit chaining in Lodash

作为 wrap-chain-unwrap 模式的替代方案(它本身没有错,但替代方案总是很有趣)还有另一种方法可以检查。

尝试利用 _.flow

想法是 flow 中的每个函数都将接收前一个函数的输出作为输入,这正是您所需要的。 一个例子,给定这个数据:

var foundUser = {
    charData: []
};

var rows = [{ok: 1, blah: 'nope'}];

使用Lodash FP我们可以将数据作为最后一个参数传递。此功能以及 Lodash/fp 中每个方法的 auto-currying 使我们在编写函数时更轻松。这意味着我们可以拥有这个简洁而富有表现力的代码:

_.flow(
 _.assign(rows[0]),
 _.omit('blah')
)(foundUser);

// >> {"charData":[],"ok": 1}

使用标准版本的 Lodash,我们必须自己使用 _.partial 柯里化这些函数,代码肯定看起来不那么简洁,但仍然可以这样做:

_.flow(
 _.partialRight(_.assign, rows[0]),
 _.partialRight(_.omit, 'blah')
)(foundUser);

// >> {"charData":[],"ok": 1}

使用流而不是链接的一大好处是您可以轻松地将 Lodash 方法与 您自己的自定义函数 混合使用,因为 -如前所述- 他们所需要的只是作为输入的数据和作为输出的数据,除此之外别无他物:

const yourFunction = d => ({ ...d, yourProp: 4 });

_.flow(
 _.assign(rows[0]),
 yourFunction,
 _.omit('blah')
)(foundUser);

// >> {"charData":[],"ok": 1, yourProp: 4}

这使得函数组合变得更加容易和灵活,并且可以说自然会导致代码更具表现力。

还有一点要注意。如果你只安装和导入你使用的 Lodash 方法,你将只需要添加 flow 包,而不是像链接时那样添加整个 Lodash 库。

npm i --save lodash.flow

VS

npm i --save lodash

在许多 real-world 应用程序中,拥有完整构建的 Lodash 不是问题并且可以说更容易保持最新状态的应用程序可能是一个微不足道的优势,但在您编写库或脚本时非常方便将作为第三方工具分发使用。在这种情况下,您将能够在分布式大小方面保持更低的足迹。

Lodash 方法文档:

值得一读的文章:

其他一些注意事项:

  • 在Lodash/fp Flow 别名为_.pipe,所以你可以选择你喜欢的。

  • 如果您更喜欢从右到左的构图,也可以使用 _.flowRight(或其 fp 别名 _.compose),如 Ramda's compose 所示.

示例:

_.flow(
 _.assign(rows[0]), // #1st to execute
 yourFunction,  // #2
 _.omit('blah'),  // #3
)(foundUser);

// is the same as...

_.flowRight(
 _.omit('blah'), // #3rd to execute
 yourFunction, // #2
 _.assign(rows[0]), // #1
)(foundUser);

你试过lodash/fp吗?它具有所有相同的功能,但它们是柯里化的,并且 none 改变了输入。

正因为如此,您可以用非常好的方式组合它们。

示例:

import moment from 'moment'
import { compose, filter, groupBy, size, sortBy } from 'lodash/fp'

const fromAdmin = filter({ type: 'admin' })
const groupedByDate = groupBy(message => moment(message.createdAt).format('YYYYMMDD'))
const sorted = sortBy('createdAt')
const unreadByUser = filter({ isReadByUser: false })

const groupedMessages = compose(
  groupedByDate,
  sorted,
  unreadByUser,
  fromAdmin,
)(messages)

Chain 是 lodash 中管道的最佳等价物。

_.chain(foundUser)
 .assignIn(rows[0])
 .omit(['blah'])
 .value()

您还可以通过 .tap.thru 链接一些自定义函数,例如:

_.chain(foundUser)
 .assignIn(rows[0])
 .tap(console.log)
 .omit(['blah'])
 .value()