如何在支持树摇动的同时将`chain`与`lodash-es`一起使用?

问题描述 投票:0回答:4

众所周知,

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(', ')
}

编辑#1:

重点不是

chain
如何导入,而是其他
chained
函数如何导入

javascript method-chaining lodash
4个回答
14
投票

编辑:正如 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]);

这个例子(以及更多)来自这篇文章


1
投票

我发现了关于如何构建自己的链的更简单但更狡猾的答案。

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()

0
投票

新答案

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
中。


0
投票

具有
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
行为。

这增加了一些额外的语法,但您可能会发现它足够可读。

© www.soinside.com 2019 - 2024. All rights reserved.