为什么有人更喜欢Lodash或Underscore.js实用程序库而不是另一个?
Lodash 似乎是下划线的替代品,后者的使用时间更长。
我认为两者都很出色,但我对它们如何进行有根据的比较知之甚少,我想了解更多关于差异的信息。
为什么有人更喜欢Lodash或Underscore.js实用程序库而不是另一个?
Lodash 似乎是下划线的替代品,后者的使用时间更长。
我认为两者都很出色,但我对它们如何进行有根据的比较知之甚少,我想了解更多关于差异的信息。
arguments
我创建 Lodash 是为了为数组、字符串、对象和对象1提供更一致的跨环境迭代支持。它已经成为 Underscore.js 的超集,提供更一致的 API 行为、更多功能(如 AMD 支持、深度克隆和深度合并)、更全面的文档和单元测试(在Node.js、RingoJS、Rhino中运行的测试) 、Narwhal、PhantomJS和浏览器),更好的整体性能和大型数组/对象迭代的优化,以及自定义构建和模板预编译实用程序的更大灵活性。
由于 Lodash 比 Underscore.js 更新更频繁,因此提供lodash underscore
了一个构建以确保与 Underscore.js 的最新稳定版本兼容。
有一次,我什至获得了对 Underscore.js 的推送访问权限,部分原因是 Lodash 负责提出 30 多个问题;在 Underscore.js v1.4.x+ 中登陆错误修复、新功能和性能提升。
此外,至少有三个Backbone.js样板默认包含 Lodash,并且 Lodash 现在在 Backbone.js 的官方文档中被提及。
查看 Kit Cambridge 的帖子,向 Lo-Dash 说“Hello”,以更深入地了解 Lodash 和 Underscore.js 之间的差异。
脚注:
arguments
对象的支持不一致。在较新的浏览器中,Underscore.js 方法忽略数组中的漏洞,“对象”方法迭代arguments
对象,字符串被视为类似数组,方法正确地迭代函数(忽略它们的“原型”属性)和对象(迭代阴影属性,如“toString " 和 "valueOf"),而在旧版浏览器中则不会。此外,Underscore.js 方法,如_.clone
,保留数组中的孔,而其他方法_.flatten
则不保留。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 文档)
如果您像我一样期待 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 是浅的- Underscore
_.groupBy
支持传递参数(value, index, originalArray)
的迭代器,而在 Lodash 中,迭代器 for_.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
- 下划线
_.uniq
是iteratee
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
out 拆分为
_.take
,_.takeRight
,_.drop
, &_.dropRight
(即在 Underscore.js_.head(array, 2)
中是_.take(array, 2)
在 Lodash 中)
除了John 的回答,阅读 Lodash(迄今为止我一直认为它是 Underscore.js 的“我也是”),以及查看性能测试、阅读源代码和博客文章之外,还有几点使 Lodash 优于 Underscore.js 的有以下几点:
如果您查看 Underscore.js 的源代码,您会在前几行中看到 Underscore.js 依赖于许多函数的本机实现。尽管在理想情况下,这将是一种更好的方法,但如果您查看这些幻灯片中给出的一些性能链接,不难得出结论,这些“本机实现”的质量因浏览器而异——到浏览器。Firefox 在某些功能上非常快,而在某些 Chrome 中占主导地位。(我想在某些情况下 Internet Explorer 也会占主导地位)。我认为最好选择跨浏览器性能更一致的代码。
一定要早点阅读这篇博文,不要因为它而相信它,而是通过运行基准来自己判断。我现在惊呆了,看到 Lodash在 Chrome 等简单的原生函数中的性能比 Underscore.js 快 100-150%
Array.every
!
这是Lodash 之间的差异列表,它的 Underscore.js 构建是您的 Underscore.js 项目的直接替代品。
在 2014 年,我仍然认为我的观点成立:
恕我直言,这个讨论被夸大了。引用上述博客文章:
大多数 JavaScript 实用程序库,例如 Underscore、Valentine 和 wu,都依赖于“native-first dual approach”。这种方法更喜欢原生实现,只有在不支持原生等价物的情况下才回退到原生 JavaScript。但是 jsPerf 揭示了一个有趣的趋势:迭代数组或类似数组的集合的最有效方法是完全避免原生实现,而是选择简单的循环。
好像“简单循环”和“vanilla Javascript”比 Array 或 Object 方法实现更原生。哎呀...
拥有单一的事实来源当然很好,但没有。即使你被告知不是这样,也没有香草之神,亲爱的。对不起。唯一真正成立的假设是,我们都在编写旨在在所有主流浏览器中表现良好的 JavaScript 代码,并且知道它们都有相同事物的不同实现。委婉地说,这是一个要应付的婊子。但这是前提,不管你喜不喜欢。
也许你们所有人都在从事需要 twitter 性能的大型项目,以便您现在真正看到每秒列表中 850,000 (Underscore.js) 与 2,500,000 (Lodash) 迭代之间的区别!
我不是。我的意思是,我从事的项目必须解决性能问题,但这些问题从未得到解决,也不是由 Underscore.js 和 Lodash 引起的。除非我掌握了实现和性能(我们现在正在谈论 C++)的真正差异,比如说,一个可迭代的循环(对象或数组,稀疏与否!),我宁愿不被打扰任何声明都基于已经自以为是的基准平台的结果。
它只需要一个单一的更新,比方说,Rhino以一种方式将它的 Array 方法实现点燃,没有一个单一的“中世纪循环方法性能更好,永远和诸如此类”的牧师可以围绕一个简单的事实争论他/她的方式突然之间,Firefox 中的数组方法比他/她自以为是的笨蛋要快得多。伙计,你不能通过欺骗你的运行时环境来欺骗你的运行时环境!宣传的时候想想...
你的实用腰带
... 下次。
所以要保持相关性:
选择最适合您需求的任何方法。照常。我更喜欢在任何时候对实际实现进行回退,而不是自以为是的运行时作弊,但即使这在当今似乎也是一个品味问题。坚持使用像http://developer.mozilla.com和http://caniuse.com这样的优质资源,你会没事的。
我同意这里所说的大部分内容,但我只想指出一个支持 Underscore.js 的论点:库的大小。
特别是如果您正在开发一个打算主要在移动设备上使用的应用程序或网站,则生成的捆绑包的大小以及对启动或下载时间的影响可能具有重要作用。
作为比较,这些尺寸是我在运行Ionic serve 后使用 source-map-explorer 注意到的尺寸:
Lodash: 523 kB
Underscore.js: 51.6 kB
可以使用BundlePhobia检查Lodash和Underscore.js的当前大小。
我不确定这是否是 OP 的意思,但我遇到了这个问题,因为我正在搜索从 Underscore.js 迁移到 Lodash 时必须牢记的问题列表。
如果有人发布一篇包含此类差异的完整列表的文章,我将不胜感激。让我从我艰难地学到的东西开始(也就是说,让我的代码在生产中爆炸的东西:/):
_.flatten
在 Underscore.js 中默认是深的,您必须将 true 作为第二个参数传递以使其变浅。在 Lodash 中,默认情况下它是浅的,并且将 true 作为第二个参数传递将使它变深!:)_.last
在 Underscore.js 中接受第二个参数,它告诉你想要多少元素。在 Lodash 中没有这样的选项。你可以用.slice
_.first
(同样的问题)_.template
在 Underscore.js 中可以有多种使用方式,其中之一是提供模板字符串和数据并返回 HTML(或者至少前一段时间它是这样工作的)。在 Lodash 中,您会收到一个函数,然后您应该将数据提供给该函数。_(something).map(foo)
在 Underscore.js 中工作,但在 Lodash 中我不得不将其重写为_.map(something,foo)
. 也许这只是一个TypeScript
问题。Ben McCormick 的Underscore vs Lo-Dash是比较两者的最新文章:
- Lodash 的 API 是 Underscore.js 的超集。
- 在引擎盖下,Lodash 已被完全重写。
- Lodash 绝对不比 Underscore.js 慢。
- Lodash 增加了什么?
- 可用性改进
- 额外功能
- 性能提升
- 链接的简写语法
- 自定义构建以仅使用您需要的内容
- 语义版本控制和 100% 的代码覆盖率
我刚刚发现了一个对我来说很重要的区别。Lodash 的非Underscore.js 兼容版本_.extend()
不会复制类级别定义的属性或方法。
我在CoffeeScript中创建了一个Jasmine测试来证明这一点:
https://gist.github.com/softcraft-development/1c3964402b099893bd61
幸运的是,lodash.underscore.js
保留了 Underscore.js 复制所有内容的行为,这对我来说是所需的行为。
Lodash 拥有与 Underscore.js_.mapValues()
相同的_.mapObject()
.
在大多数情况下,Underscore.js 是 Lodash 的子集。
有时,就像现在一样,Underscore.js 会有 Lodash 没有的很酷的小功能,比如 mapObject。这为我的项目开发节省了很多时间。