Lodash和Ramda之间的区别

26

我最近研究了一些关于JS框架的内容。从我所看到的来看,其中两个最流行和现代的库是LodashRamda (对吗?)。

我看到有一个类似的问题涉及到Lodash和Underscore。然而,我没有看到任何与Lodash和Ramda相关的内容。而且说实话,我也找不到任何基准测试。

它们有什么区别呢? 用例又如何呢? 哪一个更好呢?

1个回答

80

免责声明:我是Ramda的创始人和主要维护者之一,所以我相信这个答案会包含一些个人偏见。我会尽力控制好不让它失控。

概述

关于问题的这部分:

哪一个更好?

没有人能够明确地回答这个问题。这取决于你的需求、历史、编程口味和无数更加模糊的因素。

当然,我对Ramda有偏见,但我仍然不会告诉你哪一个更好。

但是这两者在功能上有显著的重叠,在基本哲学上有显著的差异。

它们都是实用函数的抓包,函数之间几乎没有任何连贯性。也就是说,它们是库而不是框架。它们根本不试图确定你如何编写或组织代码。

它们有很多重叠。在305个当前lodash函数和261个当前Ramda函数中,有103个共享名称,而且几乎总是具有类似的目的。剩下的函数可能有一半可以在其他库中找到,但是名称不同。

简要历史

尽管在它之前有一些实验性的函数库,但Underscore是将许多这些概念带入Javascript主流的一个库。它曾经独自站立一段时间,成为这个领域中无可争议的领导者。

但是它的性能存在问题。最终lodash在很大程度上被创建出来是为了用更好的性能做同样的事情。通过创建自定义版本的经典函数,例如map,而不是默认使用JS引擎内置的函数,lodash很快就能够胜过Underscore。但它最初是作为Underscore的替代品而开始的,并且长时间保持着这种关注点。

Ramda的创始人们对Reginald Braithwaite的JavaScript Allongé中的思想印象深刻,并创建了Ramda作为教育工具,以帮助将这些思想转化为实用的库。他们更关注干净的API和函数组合,以及不可变数据和无副作用编码,而不是性能。通过一系列奇怪的事件,它最终变得非常受欢迎。

这些天你很少听到Underscore的消息。它仍然存在,并且仍然被广泛使用,但是你不会听到太多关于它的热议。对于大多数用户来说,lodash填补了这个空间。Ramda增长迅速,但似乎已经稳定在比lodash低20-25%的下载量。但是这三个库在功能和使用方面继续增长,Underscore和Ramda的使用情况相同,远低于lodash。
有一段时间,lodash创建了一个版本,试图考虑到Ramda的一些核心问题。我个人从未使用过lodash-fp,因此无法确定其是否成功解决了这些问题。
哲学 lodash
Lodash专注于灵活性和性能。正如其创建者曾经描述的那样,它的重点在于:
提供优质的实用程序方法,以尽可能多地为开发人员提供一致性、兼容性、定制性和性能。
虽然没有通用库可以像定制编写的代码一样快,但lodash尽可能接近。
而且lodash是灵活的。几年前我写道
考虑lodash的filter:它接受数组、对象或字符串作为其集合,函数、对象、字符串或什么都不需要作为其回调,以及对象或什么都不需要作为其thisArg。你得到了一个包含24个函数的组合!
Ramda
Ramda不太关心性能,而更注重简单和清晰的API设计。 Ramda的思想是,一个函数应该只做一件事,并且应该有一个清晰的接口。 Ramda的filter函数接受一个谓词函数和一个可过滤类型的对象,并返回另一个该类型的对象。(当然,这引发了什么构成可过滤类型的问题,但这是在其文档中解决的。)
Ramda的重点是使组合函数变得简单,像所有数据都是不可变的一样工作,并避免副作用。它还包括其他函数式编程问题,例如提供镜头并使用FantasyLand规范的代数类型。
主要差异
  • Lodash (ignoring lodash-fp) functions mostly take their data first, followed by those things that work on the data, followed sometimes by optional arguments that change the behavior. Ramda puts the arguments least likely to change first, and those most likely to change last. This means that in data-transformation functions the data is last. And Ramda avoid optional arguments altogether.

  • Ramda curries all its functions, as well as nearly all the functions it returns to you. Lodash has a curry function, but you would need to call it explicitly. This is fairly central to Ramda's ideas on function composition.

  • Lodash focuses on reference-equality. Ramda focuses on value-equality. So while these are similar:

    // lodash
    _.union ([1, 2, 3, 4, 5], [2, 3, 5, 7, 11]) //=> [1, 2, 3, 4, 5, 7, 11]
    _.intersection ([1, 2, 3, 4, 5], [2, 3, 5, 7, 11]) //=> [2, 3, 5]
    
    // Ramda
    R.union ([1, 2, 3, 4, 5], [2, 3, 5, 7, 11]) //=> [1, 2, 3, 4, 5, 7, 11]
    R.intersection ([1, 2, 3, 4, 5], [2, 3, 5, 7, 11]) //=> [2, 3, 5]
    

    these act very differently:

    // lodash
    _.union (
      [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}], 
      [{x: 2}, {x: 3}, {x: 5}, {x: 7}, {x: 11}]
    )
    //=> [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}, {x: 2}, {x: 3}, {x: 5}, {x: 7}, {x: 11}]
    _.intersection (
      [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}], 
      [{x: 2}, {x: 3}, {x: 5}, {x: 7}, {x: 11}]
    ) //=> []
    
    // Ramda
    R.union (
      [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}], 
      [{x: 2}, {x: 3}, {x: 5}, {x: 7}, {x: 11}]
    )
    //=> [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}, {x: 7}, {x: 11}]
    R.intersection (
      [{x: 1}, {x: 2}, {x: 3}, {x: 4}, {x: 5}], 
      [{x: 2}, {x: 3}, {x: 5}, {x: 7}, {x: 11}]
    ) //=> [x: 2}, {x: 3}, {x: 5}]
    

    This difference is significant. Ramda's design is more closely aligned with functional systems, but it comes at a large performance price whenever equality-checking is involved. Lodash is perhaps two orders of magnitude faster than Ramda for such tasks.

  • Ramda is chiefly designed to build functions through composition, in short or long pipelines. Lodash is chiefly designed to work with imperative code. You can use either library for either job, but typical Ramda code might look like

    const myFn = R.pipe (
      R.fn1,
      R.fn2 ('arg1', 'arg2'),
      R.fn3 ('arg3'),
      R.fn4
    )
    

    where the equivalent lodash code might look like

    const myFn = (x, y) => {
      const var1 = _.fn1 (x, y)
      const var2 = _.fn2 (var1, 'arg1', 'arg2')
      const var3 = _.fn3 (var2, 'arg3')
      return _.fn4 (var3)
    }
    
  • Lodash's focus on performance means that it will supply many well-optimized functions for tasks. For instance, Lodash has all of these functions: isArguments, isArray, isArrayBuffer, isArrayLike, isArrayLikeObject, isBoolean, isBuffer, isDate, isElement, isEqual, isEqualWith, isError, isFinite, isFunction, isInteger, isLength, isMap, isMatch, isMatchWith, isNaN, isNative, isNull, isNumber, isObject, isObjectLike, isPlainObject, isRegExp, isSafeInteger, isSet, isString, isSymbol, isTypedArray, isUndefined, isWeakMap, isWeakSet.

    Ramda, by contrast expects you to supply more arguments to common functions. It has only is, isEmpty, and isNil. But it's is handles nearly all the cases above, either by calling explicitly: is (Array, [1, 2, 3]) or by partially applying to make a reusable function const isArray = is (Array)

一些差异可能会在lodash-fp中消失。但我并没有真正感受到lodash-fp是景观的一个重要组成部分。对于lodash本身,我们可以看到这些库非常不同。
性能
问题涉及基准测试。我不知道有综合基准测试套件。据传,除非涉及值相等与引用相等的问题,lodash在大多数任务中只比Ramda快10-20%。Ramda没有像lodash那样超级优化,但它的设计考虑了性能,只要满足其其他更基本的标准。
在那些涉及值相等与引用相等的情况下,lodash团队可以指出更高的速度,但Ramda团队可能会回应快速得到错误答案根本不是胜利。
目标受众
Underscore帮助将函数式编程工具带到了Javascript。它是一个通用的实用程序库,并为任何想要提高生产力的JS开发人员设计。Lodash继承了这个焦点。两者都是以开发人员舒适度为中心编写的。
Ramda的受众范围更为局限。它是为那些不仅想从函数式编程中获取特定工具,而且想要采用其更基本的思想,如函数纯度和数据不可变性的人而设计的。它旨在让JS开发人员以更FP风格移动,以及那些想要以熟悉的方式使用JS的FP语言的人。它是以简洁为中心编写的。
总结
这些库在功能上有很大的重叠。但它们的设计、基础哲学和开发人员体验都非常不同。
如果您在它们之间进行选择,则根据上述内容有一个正确的答案,但并没有明确的最佳库适用于所有人。
您还应考虑是否需要它们。开发自己的可重用函数列表以包含需要它们的任何项目并不难。该平台比这些库构思时更具可行性。

3
使用_.unionBy_.intersectionBy可以得到与R.unionR.intersection相同的答案。 - foxiris
2
@foxiris:完全正确,Ramda 有 unionWith(我不确定为什么没有 differenceWith!)。 因此,R .unionWith (R .identical) 应该与 _.union 行为相同。 区别在于库的哲学所认为的默认行为和期望行为,而不是你可以使用它们实现什么。 - Scott Sauyet
1
非常好的解释,这确实帮助我理解了这两个库。谢谢! - Daniel Jung
1
Lodash有它的fp版本,所以在我看来,你对可组合性的比较应该更新,除此之外,答案非常棒。 - R01010010
1
@R01010010:我确实多次提到了lodash-fp,但我并没有感觉它是整个编程领域的重要组成部分,而且看起来它正在逐渐消失 - Scott Sauyet
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接