简体   繁体   English

Lodash 和 Ramda 的区别

[英]Differences between Lodash and Ramda

So I've been researching a little bit about JS frameworks.所以我一直在研究一些 JS 框架。 From what I saw, two of the most popular and modern libraries are Lodash and Ramda (right?).据我所知,两个最流行的现代库是LodashRamda (对吧?)。

I saw a similar question regarding Lodash and Underscore.我看到了一个关于 Lodash 和 Underscore 的类似问题 However, I didn't see anything related to Lodash and Ramda.但是,我没有看到任何与 Lodash 和 Ramda 相关的内容。 Also I couldn't find any benchmark to be honest.老实说,我也找不到任何基准。

What are the differences?有什么区别? How about the use cases?用例怎么样? Which one is better?哪一个更好?

Dislaimer : I'm one of the founders and chief maintainers of Ramda, so I'm sure this answer will include some personal bias.免责声明:我是Ramda的创始人和首席维护者之一,所以我确信这个答案会包含一些个人偏见。 I'll try hard not to let it get out of hand.我会努力不让它失控。

Overview概述

As to this part of the question:关于这部分问题:

Which one is better?哪一个更好?

There is no way anyone here can answer that definitively.这里没有人可以明确地回答这个问题。 It depends on your requirements, your history, your programming taste, and a million even more fuzzy factors.这取决于您的要求、您的历史、您的编程品味以及一百万个甚至更多的模糊因素。

I'm biased in favor of Ramda, of course, but I still won't try to tell you which one is better.当然,我偏向于 Ramda,但我仍然不会试图告诉你哪个更好。

But there are significant overlaps in capability between these two and significant differences in underlying philosophy.但是这两者之间在能力上有很大的重叠,在基本理念上也有很大的不同。

Both are grab-bags of utility function, with little or no cohesion between the functions.两者都是实用程序 function 的抓包,功能之间几乎没有内聚性。 That is, they are libraries and not frameworks .也就是说,它们是而不是框架 They don't at all try to determine how you write or organize your code.他们根本不会尝试确定您如何编写或组织代码。

They have a great deal of overlap.它们有很多重叠。 Among the 305 current lodash functions and the 261 current Ramda ones, there are 103 with shared names, and almost always, similar purpose.在 305 个当前的 lodash 函数和 261 个当前的 Ramda 函数中,有 103 个具有相同的名称,而且几乎总是具有相似的目的。 Probably half the remaining functions are found in the other library under different names.其余功能的一半可能在其他库中以不同的名称找到。

A Brief History一个简短的历史

Although there were some experimental functional libraries before it, Underscore was the one that brought many of these concepts to the mainstream of Javascript. It stood alone for a while as the undisputed leader in this space.尽管之前有一些实验性的函数库,但Underscore是将其中许多概念带入 Javascript 主流的那个。它作为该领域无可争议的领导者独树一帜了一段时间。

But there were problems with its performance.但它的性能存在问题。 Eventually lodash was created in large part to try to do the same thing with better performance.最终, lodash的创建在很大程度上是为了尝试以更好的性能做同样的事情。 By creating custom versions of classic functions like map , rather than defaulting to the JS engine's built-in ones, lodash was quickly able to outperform Underscore.通过创建像map这样的经典函数的自定义版本,而不是默认使用 JS 引擎的内置函数,lodash 很快就能超越 Underscore。 But it started as a drop-in replacement for Underscore, and kept that focus for a long while.但它最初是作为 Underscore 的直接替代品,并在很长一段时间内保持了这种关注。

The Ramda founders were impressed with the ideas in Reginald Braithwaite's JavaScript Allongé and created Ramda as an educational tool to help turn these ideas into a pragmatic library. Ramda的创始人对 Reginald Braithwaite 的JavaScript Allongé中的想法印象深刻,并创建了 Ramda 作为一种教育工具,以帮助将这些想法变成一个实用的图书馆。 They were less focused on performance, and more on a clean API and functional composition, as well as immutable data and side-effect-free coding.他们不太关注性能,而是更关注干净的 API 和功能组合,以及不可变数据和无副作用的编码。 Through an odd series of events, it eventually grew quite popular.通过一系列奇怪的事件,它最终变得非常流行。

These days you don't hear much about Underscore.这些天你听不到太多关于 Underscore 的消息。 It's still out there, and still used a fair bit, but you don't hear much buzz.它仍然在那里,并且仍然使用了一些,但你听不到太多的嗡嗡声。 For most users, lodash fills that space well.对于大多数用户来说,lodash 很好地填补了这个空间。 Ramda grew quickly, but seems to have settled down at about 20 - 25% of the downloads that lodash gets. Ramda 增长迅速,但似乎已经稳定在 lodash 获得的下载量的 20-25% 左右。 But all three libraries continue to grow in capability and in usage, with Underscore and Ramda about the same usage, far below lodash.但是这三个库在功能和使用上都在继续增长,Underscore 和 Ramda 的使用率大致相同,远低于 lodash。

At one point, lodash created a version that tries to take into account some of Ramda's core concerns.有一次,lodash 创建了一个版本,试图考虑 Ramda 的一些核心问题。 I personally have never used lodash-fp so I can't speak to how successfully it does this.我个人从未使用过 lodash-fp ,所以我不能说它有多成功。

Philosophy哲学

lodash lodash

Lodash focuses on flexibility and performance. Lodash 专注于灵活性和性能。 Its focus, as its creatoronce described , is on正如其创建者曾经描述的那样,它的重点是

providing quality utility methods to as many devs as possible with a focus on consistency, compatibility, customization, and performance.为尽可能多的开发人员提供高质量的实用方法,重点关注一致性、兼容性、定制和性能。

While no general-purpose library can ever be quite as fast as custom-written code, lodash gets as close as possible.虽然没有任何通用库可以像自定义编写的代码一样快,但 lodash 已经尽可能接近了。

And lodash is flexible.而且 lodash 是灵活的。 I wrote several years ago我几年前写过

Consider lodash's filter : It accepts an array, object, or string for its collection, a function, object, string, or nothing at all for its callback, and an object or nothing at all for its thisArg .考虑 lodash 的filter :它接受一个数组 object 或字符串作为它的集合,一个 function、object 字符串,或者什么都没有作为它的回调,一个 object 或者什么也没有作为它的thisArg You're getting 3 * 4 * 2 = 24 functions in one!您将获得 3 * 4 * 2 = 24 个函数!

Ramda拉姆达

Ramda is less concerned with performance, and more with simple and clean API design. Ramda 不太关心性能,更关心简单干净的 API 设计。 The idea for Ramda is that a function should do one thing only, and should have a single clear interface. Ramda 的想法是 function 应该只做一件事,并且应该有一个清晰的界面。 Ramda's filter function takes a predicate function and an object of a filterable type, and returns another object of that type. Ramda 的filter function 采用谓词 function 和一个可过滤类型的 object,并返回另一个该类型的 object。 (Of course this raises the question of what constitutes a filterable type, but that's for its documentation.) (当然,这提出了什么构成可过滤类型的问题,但那是为了它的文档。)

Ramda's focus is on making it simple to compose functions, to work as though all data is immutable, and to avoid side-effects. Ramda 的重点是使组合函数变得简单,就像所有数据都是不可变的一样工作,并避免副作用。 It also incorporates other functional programming concerns, such as supplying lenses and working with the algebraic types of the FantasyLand specification .它还包含其他函数式编程问题,例如提供镜头和使用FantasyLand 规范的代数类型。

Key Differences主要区别

  • 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. Lodash(忽略 lodash-fp)函数大多首先获取它们的数据,然后是处理数据的那些东西,有时是可选的 arguments 来改变行为。 Ramda puts the arguments least likely to change first, and those most likely to change last. Ramda 将最不可能改变的 arguments 放在最前面,最有可能改变的放在最后。 This means that in data-transformation functions the data is last.这意味着在数据转换函数中数据是最后的。 And Ramda avoid optional arguments altogether.并且 Ramda 完全避免了可选的 arguments。

  • Ramda curries all its functions, as well as nearly all the functions it returns to you. Ramda 柯里化了它的所有函数,以及它返回给你的几乎所有函数。 Lodash has a curry function, but you would need to call it explicitly. Lodash 有一个curry function,但您需要显式调用它。 This is fairly central to Ramda's ideas on function composition.这是 Ramda 关于 function 组合的想法的核心。

  • Lodash focuses on reference -equality. Lodash 专注于引用相等性。 Ramda focuses on value -equality. Ramda 专注于价值平等。 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. Ramda 的设计与功能系统更紧密地结合在一起,但只要涉及到相等性检查,它就会付出很大的性能代价。 Lodash is perhaps two orders of magnitude faster than Ramda for such tasks.对于此类任务,Lodash 可能比 Ramda 快两个数量级。

  • Ramda is chiefly designed to build functions through composition, in short or long pipelines. Ramda 主要设计用于通过组合在短管线或长管线中构建函数。 Lodash is chiefly designed to work with imperative code. Lodash 主要设计用于命令式代码。 You can use either library for either job, but typical Ramda code might look like您可以将任一库用于任一作业,但典型的 Ramda 代码可能看起来像

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

    where the equivalent lodash code might look like等效的 lodash 代码可能看起来像

    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. Lodash 对性能的关注意味着它将为任务提供许多优化良好的功能。 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 .例如,Lodash 具有所有这些函数: isArgumentsisArrayisArrayBufferisArrayLikeisArrayLikeObjectisBooleanisBufferisDateisElementisEqualisEqualWithisErrorisFiniteisFunctionisIntegerisLengthisMapisMatchisMatchWithisNaNisNativeisNullisNumberisObjectisObjectLikeisPlainObjectisRegExpisSafeIntegerisSetisStringisSymbolisTypedArrayisUndefinedisWeakMapisWeakSet

    Ramda, by contrast expects you to supply more arguments to common functions.相比之下,Ramda 希望您为常用函数提供更多 arguments。 It has only is , isEmpty , and isNil .它只有isisEmptyisNil 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)但它几乎is处理上述所有情况,通过显式调用: is (Array, [1, 2, 3])或通过部分应用来制作可重用的 function const isArray = is (Array)

Some of these differences presumably vanish with lodash-fp.其中一些差异可能会随着 lodash-fp 消失。 But I don't get any real sense that lodash-fp is a major part of the landscape.但我并没有真正意识到 lodash-fp 是景观的主要部分。 And for lodash proper, we can see that the libraries are quite different.而对于 lodash 本身,我们可以看到这些库非常不同。

Performance表现

The question asked about benchmarks.该问题询问了基准。 I know of no comprehensive benchmark suite.我知道没有全面的基准套件。 Anecdotally, it seems except when the issue of value-equality vs reference-equality is involved, lodash is 10 - 20% faster at most tasks.有趣的是,似乎除非涉及价值平等与参考平等的问题,否则 lodash 在大多数任务中的速度要快 10-20%。 Ramda is not as hyper-optimized as lodash, but it is written with performance in mind, so long as its other more fundamental criteria are met. Ramda 不像 lodash 那样超级优化,但它在编写时考虑到了性能,只要它的其他更基本的标准得到满足。

In those cases that do involve value-vs-reference equality, the lodash team can point to much higher speeds, but the Ramda team would probably respond that getting the wrong answer quickly is hardly a win.在那些确实涉及值与引用相等的情况下,lodash 团队可以指出更高的速度,但 Ramda 团队可能会回应说快速得到错误的答案很难算赢。

Target Audience目标听众

Underscore helped bring functional programming tools to Javascript. It is a general-purpose utility library, and was designed for any JS developer who wants to be more productive. Underscore 帮助将函数式编程工具带到 Javascript。它是一个通用实用程序库,专为任何想要提高生产力的 JS 开发人员而设计。 Lodash inherited this focus. Lodash 继承了这个重点。 Both are written with developer ergonomics a central focus.两者都是以开发人员人体工程学为中心编写的。

Ramda has a much more restricted audience. Ramda 的受众更加有限。 It is for those who want to take not just specific tools from functional programming, but who want to take its more fundamental ideas such as functional purity and data immutability.它适用于那些不仅想要从函数式编程中获取特定工具,而且还想要获取函数纯度和数据不变性等更基本思想的人。 It is aimed both at JS developers who want to move to a more FP style and at those from FP language who want to use JS in a familiar manner.它既针对想要转向更多 FP 风格的 JS 开发人员,也针对那些希望以熟悉的方式使用 JS 的 FP 语言开发人员。 It is written with simplicity a central focus.它以简单的中心焦点编写。

Summary概括

These libraries overlap a great deal in functionality.这些库在功能上有很多重叠。 But their designs, their underlying philosophies, and their developer experience are quite different.但是他们的设计、他们的基本理念和他们的开发者体验是完全不同的。

If you're choosing between them, there is a right answer for you, based on the above, but there is no clear definitive best library for everyone.如果您在它们之间进行选择,那么根据上述内容,有一个适合您的正确答案,但是没有适合每个人的明确的最佳库。

And you should also consider whether you need one at all.你还应该考虑你是否需要一个。 It's not hard to develop your own list of reusable functions to be included in whatever projects need them.开发您自己的可重用函数列表以包含在任何需要它们的项目中并不难。 The platform has become much more capable than when these libraries were conceived.该平台的功能比构想这些库时要强大得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM