lodash-es
是使用更加模块化的语法构建的,用于通过构建工具支持树摇动。
但是,
chain
相关功能意味着某些功能附加到对象/原型链。
我可以看到
chain
与 lodash-es
一起发布,但我不确定如何使用其他链接方法正确导入它。
用例可能如下所示:
import { chain } from 'lodash-es'
export function double(input) {
return chain(input)
.without(null)
.map(val => val * 2)
.value()
.join(', ')
}
重点不是
chain
如何导入,而是其他chained
函数如何导入。
编辑:正如 Snook 所指出的,关于这个主题的 a github issues 已经有工作了。所以我将其添加到我的答案中。转到Flow解决方案获取之前的答案(恕我直言,这也很好)。
import map from 'lodash-es/map';
import filter from 'lodash-es/filter';
import mapValues from 'lodash-es/mapValues';
import toPairs from 'lodash-es/toPairs';
import orderBy from 'lodash-es/orderBy';
import groupBy from 'lodash-es/groupBy';
import sortBy from 'lodash-es/sortBy';
// just add here the lodash functions you want to support
const chainableFunctions = {
map,
filter,
toPairs,
orderBy,
groupBy,
sortBy,
};
export const chain = (input) => {
let value = input;
const wrapper = {
...mapValues(
chainableFunctions,
(f) => (...args) => {
// lodash always puts input as the first argument
value = f(value, ...args);
return wrapper;
},
),
value: () => value,
};
return wrapper;
};
还有一个 TypeScript 版本,位于 lodash/lodash#3298。
你不能,
chain
需要捆绑所有(或大部分)lodash 的功能。
flow
。这是转换的示例:
import _ from "lodash";
_.chain([1, 2, 3])
.map(x => [x, x*2])
.flatten()
.sort()
.value();
进入这个:
import map from "lodash/fp/map";
import flatten from "lodash/fp/flatten";
import sortBy from "lodash/fp/sortBy";
import flow from "lodash/fp/flow";
flow(
map(x => [x, x*2]),
flatten,
sortBy(x => x)
)([1,2,3]);
这个例子(以及更多)来自这篇文章。
我发现了关于如何构建自己的链的更简单但更狡猾的答案。
import * as ld, { wrapperLodash as _ } from 'lodash-es'
ld.mixin(_, {
chain: ld.chain,
map: ld.map
})
_.prototype.value = ld.value
const emails = _.chain(users)
.map('email')
.value()
在
chain.js
中,您看到第一行是
import lodash from './wrapperLodash.js';
如果我们转到该文件,我们会找到有关如何使用惰性求值实现链接的详细说明,该惰性求值可以缩短迭代器的长度,直到调用
value()
。下面是一个导出的辅助函数,定义如下:
function lodash(value) {
if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
if (value instanceof LodashWrapper) {
return value;
}
if (hasOwnProperty.call(value, '__wrapped__')) {
return wrapperClone(value);
}
}
return new LodashWrapper(value);
}
回到
chain.js
,我们看看它是如何在 chain()
函数中使用的:
function chain(value) {
var result = lodash(value);
result.__chain__ = true;
return result;
}
本质上,
chain()
检查输入以确保它还不是包装值,如果是,则它要么返回该值(如果它是正确类的实例),要么返回新的包装值。
此实现中没有附加到任何本机原型链的方法,但它确实创建了一个名为
LodashWrapper
的新类,它使用 lodash
功能和惰性求值优化来包装输入对象。
我相信应用摇树的正确
import
声明是
import chain from 'lodash-es/chain'
这会将相同的模块导入到与问题中使用的
import
语句相同的变量,但不同之处在于运行 import { chain } from 'lodash-es'
会评估 lodash.js
中导入的 all,而我的 import
方法只触及 chain.js
文件及其必要的依赖项位于 wrapperLodash.js
中。
lodash-es/flow
我采用了另一种方法,它不依赖于修改 lodash 内部结构,并且仍然保持树抖动。
import { flow, map, flatten, sortBy } from "lodash-es";
export const f = <V, I, R>(func: (v: V, i: I) => R, i: I) => (v: V) => func(v, i)
const value = flow([
f(map, x => [x, x*2]),
flatten,
f(sortBy, x => x)
])([3,1,2])
这个想法是手动包装每个通常采用
(value, iteratee)
参数的函数,并使用高阶函数f()
,该函数也接受迭代器,并输出值优先的等价物。换句话说,您将函数转换为其 lodash/fp
行为。
这增加了一些额外的语法,但您可能会发现它足够可读。