题 lodash和下划线之间的差异


为什么有人会更喜欢 lodash.js 要么 underscore.js 实用程序库超过其他?

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

我认为两者都很精彩,但我对他们如何努力进行有根据的比较并不了解,我想更多地了解这些差异。


1405
2017-12-09 17:08


起源


你可能想看一些 屏幕类型转换 关于在其github页面上链接的lodash。就个人而言,我一直在使用underscore.js,但更多是因为这就是我开始使用的,正如你所说的更长。 - Jack
lodash 和 underscore 在... 合并线程 现在 - zangw
供参考: Underscore&Lodash便笺簿 - user2875289


答案:


我创建了Lo-Dash,为数组,字符串,对象和数组提供更一致的跨环境迭代支持 arguments 对象1。它已成为Underscore的超集,提供更一致的API行为,更多 特征 (像AMD支持,深度克隆和深度合并),更彻底 文件 和单元测试(在Node,Ringo,Rhino,Narwhal,PhantomJS和浏览器中运行的测试),更好的整体性能和对大型数组/对象迭代的优化,以及更大的灵活性 自定义构建 和模板预编译实用程序。

因为Lo-Dash比Underscore更频繁更新,a lodash underscore 建立 提供 确保与最新稳定版本的Underscore兼容。

有一次,我甚至被给予了 推送访问 到Underscore,部分是因为Lo-Dash负责筹集超过30个问题; Underscore v1.4.x +中的登陆错误修复,新功能和性能提升。

此外,至少有3个Backbone样板,默认包含Lo-Dash,现在Backbone的官方提到了Lo-Dash 文件

查看Kit Cambridge的帖子, 对Lo-Dash说“你好”,有关Lo-Dash和Underscore之间差异的更深层细分。

脚注:

  1. Underscore对数组,字符串,对象和 arguments 对象。在较新的浏览器中,Underscore方法会忽略 数组中的孔,“对象”方法迭代 arguments 对象,字符串被视为类似数组,并且方法正确地迭代函数(忽略它们的“原型”属性)和对象(迭代阴影属性,如“toString”和“valueOf”),而在旧版浏览器中它们则不会。另外,Underscore方法也是如此 _.clone 保留数组中的空洞,而其他人喜欢 _.flatten 别。

1780
2017-12-16 05:34



@Brian - 在开发Lo-Dash的过程中,我继续提出这样的问题:“在Lo-Dash中,有什么人能指出,与Underscore相比,这是一个负面因素?”然后解决它们。这就是为什么我加强了文档,添加自定义构建,并使源更具可读性。 - John-David Dalton
我喜欢lo-dash而且我正在使用它,所以请不要认为我在抨击,但为什么不贡献下划线而不是创建一个新的库? - Xananax
@Xananax - 检查评论主题: github.com/jashkenas/underscore/commit/...  - 这可能会回答这个问题。 - Robert Grant
有没有努力将lodash合并回下划线? - streetlight
哦,政治。我只想要一个图书馆。 - ooolala


Lo-Dash的灵感来自下划线,但现在是卓越的解决方案。你可以做你的 自定义构建, 有一个 更高的性能,支持AMD和 很棒的额外功能。检查一下 Lo-Dash vs Underscore基准 在jsperf和..这 关于lo-dash的精彩帖子

使用集合时最有用的功能之一是简写语法:

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

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

// using underscore
_.filter(characters, function(character) { return character.age === 36; } );

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

(取自 lodash docs


165
2017-12-13 21:51



Kit Cambridge博客的链接非常丰富。 - Brian M. Hunt
我认为这是错误的(这个例子)。截至上一次更新1.8.3,你可以像lodash一样使用pluck。无论如何对于以前的版本我不认为下划线会暴露一个与地图相同的函数(你的下划线示例看起来像一个地图函数) - alexserver
filter 从2012年开始的下划线功能 github.com/jashkenas/underscore/issues/648 (它的名字是 where) - Muhammad Hewedy


除了John的回答,还读起lodash(我以前认为它是“me-too”以强调),并看到性能测试,阅读源代码,以及 博客文章,使得lodash远远优于下划线的几点是:

  1. 这与速度无关 一致性 速度(?)

    如果你看一下下划线的源代码,你会在前几行中看到下划线反映在许多函数的本机实现上。虽然在一个理想的世界中,如果你看一下给定的一些perf链接,这将是一个更好的方法 这些幻灯片,不难得出这些“本机实现”的质量在浏览器到浏览器之间变化很大的结论。 Firefox的一些功能很快,而且在一些Chrome中占主导地位。 (我想在某些场景中IE也会占据主导地位)。我相信最好选择一个代码 性能 在浏览器中更加一致。

    请先阅读博客文章,而不是相信它本身,通过运行来判断自己 基准。我现在很震惊,看到一个lodash甚至比下划线快100-150% 简单本地人 功能如 Array.every 在Chrome中!

  2. 演员 在lodash中也很有用。

  3. 至于Xananax的高度评价意见表明对下划线代码的贡献:总是更好  竞争,不仅可以保持创新,还可以促使您保持自己(或图书馆)的良好状态。

这里有一个 差异列表 在lodash之间,它的下划线构建是你的下划线项目的替代品。


57
2017-08-18 14:18



在哪种情况下,“速度的一致性”值?假设我有一个在FF和IE中速度为100%的方法,本机实现的IE速度为80%,FF为120%(反之亦然)。然后我会说在FF中使用本机实现和IE中自己的实现会很好。我无法想象任何情况,我会说:让我们放慢速度只是因为它有与IE中相同的速度。代码的大小和可维护性或所有浏览器的平均减速都是参数,但速度的一致性? - stofl
我的意思是,“始终加快速度” - kumar_harsh
一辆20公里的汽车一天不会用得太多:) - kumar_harsh
我倾向于回退到浏览器的本机实现,因为在大多数情况下它具有可接受的性能并且可以通过浏览器更新来改进而无需担心使库保持最新。 - orad
@KumarHarsh也许我没说好。我的意思是我倾向于使用内部使用本机函数的库(如果可用),而不是总是更喜欢自己的实现。 - orad


如果像我一样,你期待下划线和lodash之间的使用差异列表,那就是 从下划线迁移到lodash的指南

以下是后人的当前状态:

  • 下划线 _.compose 是Lodash _.flowRight
  • 下划线 _.contains 是Lodash _.includes
  • 下划线 _.findWhere 是Lodash _.find
  • 下划线 _.invoke 是Lodash _.invokeMap
  • 下划线 _.mapObject 是Lodash _.mapValues
  • 下划线 _.pluck 是Lodash _.map
  • 下划线 _.where 是Lodash _.filter
  • 下划线 _.any 是Lodash _.some
  • 下划线 _.all 是Lodash _.every
  • 下划线 _.each 不允许退出退出 false
  • 下划线 _.flatten Lodash很浅,默认很深
  • 下划线 _.isFinite 不符合 Number.isFinite
       (例如。 _.isFinite('1') 回报 true 在Underscore但是 false 在   Lodash)
  • 下划线 _.matches 速记不支持深度比较
       (例如。 _.filter(objects, { 'a': { 'b': 'c' } })
  • 下划线≥1.7&Lodash改变了他们的 _.template 语法到
    _.template(string, option)(data)
  • Lodash _.uniq 不接受 iteratee 像Underscore的功能。使用Lodash _.uniqBy
  • Lodash _.first 和 ._last 不接受 n 像Underscore的论点。使用 slice
  • Lodash _.memoize 缓存是 Map 喜欢的对象
  • Lodash支持 隐式链接懒惰的链接和快捷方式   聚变
  • Lodash分裂了它的重载 _.head_.last_.rest,& _.initial 进入
      _.take_.takeRight_.drop,&    _.dropRight
       (即 _.head(array, 2) 在Underscore是    _.take(array, 2) 在Lodash)

55
2017-07-21 09:35



我在迁移时自己遇到过这些问题而且我正在维护(WIP) 交叉文档 在一个和另一个之间。希望它对其他人也有帮助! - luxon


这是2014年,而且已经太晚了几年。我仍然认为我的观点是:

恕我直言,这次讨论相当不成比例。引用前面提到的 博客文章

大多数JavaScript实用程序库,例如Underscore,Valentine和   吴,依靠“原生第一的双重方法。”这种方法更喜欢   本机实现,只有在使用时才能回归到vanilla JavaScript   不支持本机等效。但jsPerf透露了一个有趣的   趋势:迭代数组或类似数组的最有效方法   集合是为了完全避免本机实现,选择   而是简单的循环。

好像“简单循环”和“vanilla Javascript”比Array或Object方法实现更本地化。 Jeez ......

拥有单一的事实来源肯定会很好,但事实并非如此。即使你已经被告知,亲爱的,也没有香草神。对不起。唯一真正成立的假设是我们都在编写旨在在所有主流浏览器中都表现良好的Javascript代码,因为他们都知道所有浏览器都有不同的实现。温和地说,这是一个应对的婊子。但这是前提,无论你喜不喜欢。

也许你们都在研究需要叽叽喳喳表现的大型项目,以便你真正看到差异 每秒在列表上的850,000(下划线)和2,500,000(lodash)迭代之间 马上!

我一个人不是。我的意思是,我工作的项目我必须解决性能问题,但它们从未解决或由Underscore和Lo-Dash引起。除非我抓住实现和性能的真正差异(我们现在正在谈论C ++),让我们说一个循环遍及一个可迭代的(对象或数组,稀疏或不稀疏!),我宁愿不被任何困扰声称基于基准平台的结果 已经自以为是了

它只需要一个单独的更新,让我们说Rhino以一种方式设置其Array方法实现,而不是一个单独的“中世纪循环方法表现更好,永远和什么不是”牧师可以围绕简单的事实争论他/她的方式所有FF中的突然阵列方法比他/她认为的脑力训练要快得多。伙计,你不能通过欺骗你的运行时环境来欺骗你的运行时环境!在宣传时考虑一下......

你的实用腰带

... 下次。

所以要保持相关性:

  • 如果你在不牺牲本土的情况下进入方便,请使用下划线。
  • 使用Lo-Dash如果你是方便的,并且喜欢它的扩展功能目录(深层拷贝等),如果你迫切需要即时性能,最重要的是不要介意在本机API出现时立即寻求替代方案固执己见的工作。这很快就会发生。期。
  • 甚至还有第三种解决方案。 DIY!了解您的环境。了解不一致。读他们(约翰 - 大卫杰里米的代码。如果不能解释为什么真正需要一致性/兼容性层并且增强您的工作流程或提高应用程序的性能,请不要使用这个或那个。很可能您的要求满足于您完全能够自己编写的简单填充物。这两个图书馆都是普通的香草,带有一点点糖。 他们俩只是为谁最甜蜜的馅饼而战。但请相信我,最后两人都只是用水做饭。没有香草神,所以不可能没有香草教皇,对吗?

选择最适合您需求的方法。照常。我更喜欢在实际的实现上回落而不是固执的运行时作弊,但即便如此,这似乎也是现在的品味问题。坚持像优质资源 http://developer.mozilla.com 和 http://caniuse.com 你会没事的


43
2017-09-11 21:27



感谢发布Lukas。内置插件可以进一步优化吗?我收集到他们有标准所施加的限制,阻止他们进行与图书馆相当的优化,但我不知道其中的细节或者是否存在或仍然存在。 - Brian M. Hunt
例如“通过针对99%的用例进行优化,fast.js方法可以比其原生方法快5倍。” - github.com/codemix/fast.js - Brian M. Hunt
嗨,布赖恩,我很抱歉,如果这是误导,我并不是说这些库并不比他们的本机更快。如果你迫切需要表现 马上你最好使用像LoDash或fast.js这样的工具包,因为它们可以提供更快的标准方法实现。但是,如果您选择使用不依赖于本机方法的库,您可能会错过任何关于内置函数的未来性能优化。浏览器最终会进化。 - Lukas Bünger
浏览器“制造商”很难保持其浏览器标准兼容,而且性能要低得多。本机实现中的大多数性能提升都是由于硬件速度更快。 “本土实施将迎头赶上”的借口已存在多年。岁月=互联网上的永恒。 如果 原生实现一直赶上,库将被更新以使用它们。这对开源来说很酷。如果应用程序开发人员没有更新到最新的库,他们的应用程序不会突然减速,它只是不会加速。 - Andrew Steitz
......但是如果你问过他们的话 Array.from 他们可能甚至不知道应该做什么。 JS“实用带”似乎过于关注推广他们那些和蔼可亲的解决方案,他们往往会忘记这样做,实际上它们正在稀释标准化过程。不需要功能就不会给浏览器“制造商”带来压力。有趣的事实:4种主流浏览器中有2种基于开源项目(1, 2)。 - Lukas Bünger


我同意这里所说的大部分内容,但我只想指出支持underscore.js的论证:图书馆的大小。

特别是在您开发打算主要在移动设备上使用的应用程序或网站时,生成的捆绑包的大小以及对启动或下载时间的影响可能起着重要作用。

为了比较,这些大小是我在运行离子发送后使用source-map-explorer注意到的:

lodash: 523kB
underscore.js: 51.6kb

14
2018-04-26 14:20



谢谢彼得,这是值得注意的一点。其他地方有更多的讨论,包括: gist.github.com/alekseykulikov/5f4a6ca69e7b4ebed726 。 (这个答案可以通过链接其他一些讨论和引用相关位来改进)通过选择lodash的子部分以及树摇动的lodash可以减小大小的差异。 - Brian M. Hunt
感谢@ BrianM.Hunt你的回复,不知道可以包含lodash的子部分,看看吧。最近有了离子原生,Ionic也为他们的原生libs采取了这样的道路,值得注意的是,更多关注应用程序的大小 - David Dal Busco
我想知道你在哪里得到523kB? lodash.com 说它只有24kB压缩。下载的只有74kB - Martian2049
我的帖子是在2017年4月制作的。就像我在评论中所说的那样, source-map-explorer after running ionic serve - David Dal Busco
2018年3月 - lodash.min.js为72,5 kB,而underscore-min.js为16,4 kB - Combine


不确定这是否意味着OP的意思,但我遇到了这个问题,因为我正在搜索从下划线迁移到lodash时必须记住的问题列表。

如果有人发布了一篇包含这些差异的完整列表的文章,我将非常感激。让我从我学到的东西开始(也就是说,使我的代码在生产中爆炸的东西:/):

  • _.flatten 默认情况下,下划线很深,你必须传递true作为第二个参数才能使它变浅。在lodash中,默认情况下它很浅,并且传递true作为第二个参数将使其变深! :)
  • _.last 在下划线中接受第二个参数,它告诉您需要多少元素。在 lodash 没有这样的选择。你可以用它来模仿 .slice
  • _.first (同一期)
  • _.template 在下划线中可以以多种方式使用,其中一种方式是提供模板字符串和数据并获取 HTML 回来(至少那是它以前的工作方式)。在 lodash 您收到一个功能,然后您应该提供数据。
  • _(something).map(foo) 在下划线工作,但在lodash我不得不重写它 _.map(something,foo)。也许这只是一个 TypeScript-问题

9
2018-03-25 12:16



在lodash中,链接传递一个懒惰的迭代器,并且需要和端点一样 _(something).map(foo).value()。 - Brian M. Hunt
如果您使用代理调用这些库的Backbone Collection,这一切都会打动你 - 例如collection.first(5)不会给你前5个元素,而是第一个元素:) - qbolec