Lodash 和 Underscore.js 之间的差异

IT技术 underscore.js javascript lodash
2021-01-30 19:01:22

为什么会有人喜欢要么LodashUnderscore.js比其他实用程序库?

Lodash 似乎是下划线的替代品,后者已经存在的时间更长了。

我认为两者都很出色,但我对它们的工作原理知之甚少,无法进行有根据的比较,我想更多地了解它们之间的差异。

6个回答

我创建了 Lodash 来为数组、字符串、对象和arguments对象1提供更一致的跨环境迭代支持它已成为 Underscore.js 的超集,提供更一致的 API 行为、更多功能(如 AMD 支持、深度克隆和深度合并)、更全面的文档和单元测试(在Node.jsRingoJSRhino 中运行的测试)NarwhalPhantomJS和浏览器)、更好的整体性能和大型数组/对象迭代的优化,以及自定义构建和模板预编译实用程序的更大灵活性

由于 Lodash 的更新频率高于 Underscore.js,因此提供一个lodash underscore构建版本以确保与Underscore.js的最新稳定版本兼容。

有一次,我什获得了对 Underscore.js 的推送访问权限,部分原因是 Lodash 负责提出 30 多个问题;在 Underscore.js v1.4.x+ 中登陆错误修复、新功能和性能提升。

此外,至少有三个Backbone.js样板默认包含 Lodash,现在 Backbone.js 的官方文档中提到了 Lodash

查看 Kit Cambridge 的帖子,向 Lo-Dash 说“你好”,更深入地了解 Lodash 和 Underscore.js 之间的差异。

脚注:

  1. Underscore.js 对数组、字符串、对象和arguments对象的支持不一致在较新的浏览器中,Underscore.js 方法忽略数组中的漏洞,“Objects”方法迭代arguments对象,字符串被视为类数组,并且方法正确迭代函数(忽略它们的“prototype”属性)和对象(迭代像“toString”这样的阴影属性" 和 "valueOf"),而在较旧的浏览器中则不会。此外,Underscore.js 方法,例如_.clone,保留数组中的空洞,而其他方法_.flatten则不会。
我喜欢 lo-dash 并且我正在使用它,所以请不要认为我在抨击,但为什么不为下划线做出贡献而不是创建一个新库呢?
2021-03-15 19:01:22
有没有努力将 lodash 合并回下划线?
2021-03-20 19:01:22
@Brian - 在开发 Lo-Dash 时,我一直在问“与 Underscore 相比,在 Lo-Dash 中,有人可以指出什么是负面的?” 然后解决他们。这就是为什么我加强了文档,添加了自定义构建,并使源代码更具可读性。
2021-03-28 19:01:22
@Xananax - 检查评论线程:github.com/jashkenas/underscore/commit/... - 这可能会回答这个问题。
2021-03-29 19:01:22
我很想发布一些基准测试,但这可能会变得乏味。我只想说,每一个基准我已经运行已经证明罗短跑要快(MUCH比下划线在许多情况下更快)。
2021-03-31 19:01:22

Lodash 的灵感来自 Underscore.js,但现在它是一个卓越的解决方案。您可以进行自定义构建,获得更高的性能,支持 AMD 并拥有出色的额外功能检查jsperf上的 Lodash 与Underscore.js 基准测试,以及...这篇关于 Lodash 的精彩文章

当您使用集合时,最有用的功能之一是速记语法:(
尽管 Underscore 现在也支持此语法)

var characters = [
  { 'name': 'barney', 'age': 36, 'blocked': false },
  { 'name': 'fred',   'age': 40, 'blocked': true }
];

// Using "_.filter" callback shorthand
_.filter(characters, { 'age': 36 });

// Using Underscore.js
_.filter(characters, function(character) { return character.age === 36; } );

// → [{ 'name': 'barney', 'age': 36, 'blocked': false }]

(取自Lodash 文档

我认为这是错误的(采摘示例)。从上次更新 1.8.3 开始,您可以像使用 lodash 一样使用 pluck。无论如何,对于以前的版本,我认为下划线不会公开与地图相同的函数(您的下划线示例看起来像地图函数)
2021-03-21 19:01:22
filter来自 2012 github.com/jashkenas/underscore/issues/648 的下划线功能(它的名字是where
2021-03-28 19:01:22
Kit Cambridge 博客的链接非常有用。
2021-04-01 19:01:22
我在 Lo-Dash vs Underscore 基准测试链接上收到错误 500
2021-04-02 19:01:22
characters.filter(x=>x.age==36) //pure js
2021-04-10 19:01:22

如果像我一样,您期待 Underscore.js 和 Lodash 之间的使用差异列表,那么这里有一个从 Underscore.js 迁移到 Lodash 的指南

这是后代的当前状态:

  • 下划线_.any是 Lodash_.some
  • 下划线_.all是 Lodash_.every
  • 下划线_.compose是 Lodash_.flowRight
  • 下划线_.contains是 Lodash_.includes
  • 下划线_.each不允许通过返回退出false
  • 下划线_.findWhere是 Lodash_.find
  • _.flatten默认下划线很深,而 Lodash 很浅
  • 下划线_.groupBy支持传递的参数的iteratee (value, index, originalArray),而在Lodash,对于iteratee_.groupBy仅通过一个参数:(value)
  • Underscore.js_.indexOf与第三个参数undefined是Lodash_.indexOf
  • Underscore.js_.indexOf与第三个参数true是Lodash_.sortedIndexOf
  • 下划线_.indexBy是 Lodash_.keyBy
  • 下划线_.invoke是 Lodash_.invokeMap
  • 下划线_.mapObject是 Lodash_.mapValues
  • 下划线_.max结合了 Lodash _.max&_.maxBy
  • 下划线_.min结合了 Lodash _.min&_.minBy
  • 下划线_.sample结合了 Lodash _.sample&_.sampleSize
  • 下划线_.object结合了 Lodash_.fromPairs_.zipObject
  • _.omit谓词的下划线是 Lodash_.omitBy
  • 下划线_.pairs是 Lodash_.toPairs
  • _.pick谓词的下划线是 Lodash_.pickBy
  • 下划线_.pluck是 Lodash_.map
  • 下划线_.sortedIndex结合了 Lodash _.sortedIndex&_.sortedIndexOf
  • 下划线_.uniqiteratee是Lodash_.uniqBy
  • 下划线_.where是 Lodash_.filter
  • 下划线_.isFinite不对齐Number.isFinite
    (例如在 Underscore.js 中_.isFinite('1')返回true,但false在 Lodash 中)
  • 下划线_.matches速记不支持深度比较
    (例如,_.filter(objects, { 'a': { 'b': 'c' } })
  • 下划线 ≥ 1.7 & Lodash_.template语法是
    _.template(string, option)(data)
  • Lodash_.memoize缓存Map就像对象
  • Lodash 不支持支持context许多方法论点_.bind
  • Lodash 支持隐式链接惰性链接和快捷方式融合
  • Lodash 将其重载的_.head, _.last, _.rest, &拆分_.initial
    _.take, _.takeRight, _.drop, & _.dropRight
    (即在 Underscore.js_.head(array, 2)中是_.take(array, 2)在 Lodash 中)
我自己在迁移时遇到了这些问题,并且我正在维护一个 (WIP)交叉文档在一个和另一个之间进行。希望它对其他人也有帮助!
2021-03-15 19:01:22

除了约翰的回答,阅读 Lodash(我一直认为它是 Underscore.js 的“我也是”),以及查看性能测试、阅读源代码和博客文章之外,还有几点使 Lodash 优于 Underscore.js 的是这些:

  1. 这不是关于速度,而是关于速度的一致性(?)

如果您查看 Underscore.js 的源代码,您会在前几行看到 Underscore.js 回退到许多函数的本机实现。尽管在理想的世界中,这本来是一种更好的方法,但如果您查看这些幻灯片中给出的一些性能链接,不难得出结论,即这些“本机实现”的质量与浏览器的差异很大-到浏览器。Firefox 在某些功能上非常快,而在某些 Chrome 中占主导地位。(我想在某些情况下 Internet Explorer 也会占主导地位)。我认为最好选择性能在浏览器间更一致的代码

一定要早点阅读博客文章,而不是相信它,而是通过运行基准来判断自己我现在惊呆了,即使在 Chrome简单的原生函数中Lodash 的执行速度也比 Underscore.js 快 100-150% Array.every

  1. Lodash 中附加功能也非常有用。
  2. 至于 Xananax 的高度赞成的评论,建议对 Underscore.js 的代码做出贡献:拥有良好的竞争总是更好,不仅可以保持创新,还可以驱使您保持自己(或您的库)处于良好状态。

这是Lodash 之间的差异列表,它的 Underscore.js 构建是您的 Underscore.js 项目的替代品。

@KumarHarsh 也许我没有表达好。我的意思是我倾向于使用一个在内部使用本机函数(如果可用)的库,而不是总是更喜欢它自己的实现。
2021-03-12 19:01:22
我的意思是,“始终保持更快的速度”
2021-03-15 19:01:22
大小的区别呢?假设您使用 lodash 创建了一个与下划线功能完全相同的自定义构建?他们之间有很大的区别吗?我猜想重新实现会增加网站的权重。
2021-03-15 19:01:22
我倾向于回退到浏览器的本机实现,因为在大多数情况下它具有可接受的性能,并且可以随着浏览器更新而改进,而不必担心使库保持最新。
2021-03-18 19:01:22
在哪种情况下,“速度一致性”是一个值?比方说,我有一个方法在 FF 和 IE 中的速度为 100%,而本机实现的速度在 IE 中为 80%,在 FF 中为 120%(或相反)。然后我会说在 FF 中使用本机实现和在 IE 中使用自己的实现会很好。我无法想象任何情况,我会说:让我们放慢 FF 的速度,只是因为那里的速度与 IE 中的速度相同。代码的大小和可维护性或所有浏览器的平均速度都会变慢,但速度的一致性?
2021-03-19 19:01:22

在 2014 年,我仍然认为我的观点是成立的:

恕我直言,这个讨论有点过分了。引用上述博客文章

大多数 JavaScript 实用程序库,例如 Underscore、Valentine 和 wu,都依赖于“本机优先的双重方法”。这种方法更喜欢本机实现,只有在不支持本机等效项时​​才回退到 vanilla JavaScript。但是 jsPerf 揭示了一个有趣的趋势:迭代数组或类数组集合的最有效方法是完全避免本机实现,而是选择简单的循环。

好像“简单循环”和“vanilla Javascript”比数组或对象方法实现更原生。天啊...

拥有单一的真相来源当然很好,但事实并非如此。即使有人告诉你,也没有香草之神,亲爱的。抱歉。唯一真正成立的假设是,我们都在编写旨在在所有主要浏览器中表现良好的 JavaScript 代码,并且知道所有浏览器对相同的事物都有不同的实现。说得客气一点,这是个婊子要应付。但这是前提,不管你喜不喜欢。

也许你们所有人都在从事需要 twitterish 性能的大型项目,以便您现在真正看到每秒列表中 850,000 (Underscore.js) 与 2,500,000 (Lodash) 迭代之间的差异

我不是。我的意思是,我参与了一些必须解决性能问题的项目,但这些问题从未被 Underscore.js 和 Lodash 解决或导致。除非我掌握了实现和性能(我们现在谈论的是 C++)的真正差异,比如说,一个可迭代对象(对象或数组,稀疏与否!)的循环,我宁愿不要被打扰任何基于已经固执己见的基准平台结果的声明

它只需要对Rhino进行一次更新,就可以以一种方式将其 Array 方法实现设置为火,而没有一个“中世纪循环方法表现得更好,永远等等”牧师可以围绕一个简单的事实争论他/她的方式突然之间,Firefox 中的数组方法比他/她自以为是的脑残要快得多。伙计,你不能通过欺骗你的运行时环境来欺骗你的运行时环境!推广的时候想想...

你的实用腰带

... 下次。

因此,要保持相关性:

  • 如果您在不牺牲原生性的情况下获得便利,请使用 Underscore.js。
  • 如果您喜欢使用 Lodash 方便并且喜欢它的扩展功能目录(深拷贝等),并且如果您迫切需要即时性能,并且最重要的是,不要介意在原生 API 胜过自以为是的情况下尽快找到替代方案解决方法。这很快就会发生。时期。
  • 甚至还有第三种解决方案。DIY!了解您的环境。了解不一致性。阅读他们(John-DavidJeremy的)代码。不要在无法解释为什么真正需要一致性/兼容性层并增强您的工作流程或提高应用程序性能的情况下使用这个或那个。很可能您的需求可以通过一个您完全能够自己编写的简单polyfill来满足这两个库都只是加了一点糖的普通香草。他们都在为谁提供最甜的馅饼而争吵但相信我,最终两者都只是用水做饭。没有香草神,所以不可能没有香草教皇,对吧?

选择最适合您需求的方法。照常。我更喜欢在任何时候对实际实现进行回退,而不是固执的运行时作弊,但即使是现在,这似乎也是一个品味问题。坚持使用http://developer.mozilla.comhttp://caniuse.com优质资源,您会没事的。

……但如果你问他们,Array.from他们可能甚至不知道它应该做什么。JS“实用腰带”的人似乎过于关注推广他们非常友好的变通方法,以至于他们往往忘记这样做实际上是在稀释标准化过程。不需要功能不会给浏览器“制造商”带来压力。有趣的事实:4 个主要浏览器中有 2 个基于开源项目 ( 1 , 2 )。
2021-03-11 19:01:22
例如“通过针对 99% 的用例进行优化,fast.js 方法可以比它们的原生方法快 5 倍。” github.com/codemix/fast.js
2021-03-29 19:01:22
浏览器“制造商”很难让他们的浏览器标准合规,性能更差。本机实现中的大多数性能提升都是更快的硬件的结果。“本机实现将迎头赶上”的借口已经存在多年。年 = 互联网上的永恒。如果本机实现跟上,库将被更新以使用它们。这就是开源的酷炫之处。如果应用程序开发人员没有更新到最新的库,他们的应用程序不会突然变慢,只是不会加速。
2021-03-30 19:01:22
感谢张贴卢卡斯。内置插件可以进一步优化吗?我收集到它们受到标准强加的限制,这些限制阻止它们进行与库相当的优化,但我不知道细节,或者这是否是或仍然是真的。
2021-04-01 19:01:22
嗨,布赖恩,如果这是误导,我很抱歉,我并不是说这些库并不比它们的原生库快多少。如果您在性能迫切需要是正确的,现在,你为他们提供更快的标准方法的实现可能会更好过与像LoDash或fast.js的工具包。但是,如果您选择使用不依赖本机方法的库,您可能会错过任何未来对内置函数的性能优化。浏览器最终会进化。
2021-04-08 19:01:22