Différences entre lodash et souligné [fermé]

1602

Pourquoi quelqu'un préférerait-il la bibliothèque d'utilitaires lodash.js ou underscore.js à l'autre?

Lodash semble être un remplaçant pour le soulignement, ce dernier ayant été plus longtemps.

Je pense que les deux sont brillants, mais je ne sais pas assez comment ils fonctionnent pour faire une comparaison instruite, et j'aimerais en savoir plus sur les différences.

Brian M. Hunt
la source
2
Vous voudrez peut-être jeter un œil à certaines des captures d'écran sur lodash qui sont liées à sa page github. Personnellement, j'utilise underscore.js, mais plus parce que c'est ce que j'ai commencé et comme vous le dites, cela fait plus longtemps.
Jack
26
lodashet underscoresont en cours de fusion maintenant
zangw
Pour votre information: Le bloc-notes et Souligné Lodash
user2875289

Réponses:

2024

J'ai créé Lo-Dash pour fournir un support d'itération inter-environnements plus cohérent pour les tableaux, les chaînes, les objets et les argumentsobjets 1 . Il est depuis devenu un surensemble de Underscore, offrant un comportement d'API plus cohérent, plus de fonctionnalités (comme le support AMD, le clone profond et la fusion profonde), une documentation plus approfondie et des tests unitaires (tests qui s'exécutent dans Node, Ringo, Rhino, Narwhal, PhantomJS et navigateurs), de meilleures performances globales et optimisations pour les grands tableaux / itérations d'objets, et plus de flexibilité avec les builds personnalisés et les utilitaires de pré-compilation de modèles.

Étant donné que Lo-Dash est mis à jour plus fréquemment que Underscore, une lodash underscoreversion est fournie pour garantir la compatibilité avec la dernière version stable d'Underscore.

À un moment donné, on m'a même donné un accès push à Underscore, en partie parce que Lo-Dash est responsable de soulever plus de 30 problèmes; corrections de bogues d'atterrissage, nouvelles fonctionnalités et gains de performances dans Underscore v1.4.x +.

De plus, il existe au moins 3 plaques chauffantes Backbone qui incluent Lo-Dash par défaut et Lo-Dash est maintenant mentionné dans la documentation officielle de Backbone .

Consultez la publication de Kit Cambridge, dites «Bonjour» à Lo-Dash , pour une ventilation plus approfondie des différences entre Lo-Dash et Underscore.

Notes de bas de page:

  1. Underscore a un support incohérent pour les tableaux, les chaînes, les objets et les argumentsobjets. Dans les navigateurs plus récents, les méthodes Underscore ignorent les trous dans les tableaux , les méthodes "Objects" itèrent les argumentsobjets, les chaînes sont traitées comme des tableaux et les méthodes itèrent correctement les fonctions (ignorant leur propriété "prototype") et les objets (itérant les propriétés ombrées comme "toString" et "valueOf"), contrairement aux anciens navigateurs. En outre, les méthodes de soulignement comme la _.clonepréservation des trous dans les tableaux, tandis que d'autres _.flattenn'aiment pas.
John-David Dalton
la source
174
@Brian - Lors du développement de Lo-Dash, j'ai continué à poser la question "Qu'est-ce que quelqu'un pourrait indiquer, dans Lo-Dash, comme négatif par rapport à Underscore?" puis les aborder. C'est pourquoi j'ai étoffé la documentation, ajouté des versions personnalisées et rendu la source plus lisible.
John-David Dalton
10
Je suis très tenté de publier quelques repères, mais cela pourrait devenir fastidieux. Il suffit de dire que chaque benchmark que j'ai exécuté a prouvé que Lo-Dash est plus rapide ( BEAUCOUP plus rapide dans de nombreux cas) que le soulignement.
Wil Moore III
186
J'adore lo-dash et je l'utilise, alors ne pensez pas que je dénonce, mais pourquoi ne pas contribuer à souligner au lieu de créer une nouvelle bibliothèque?
Xananax
133
@Xananax - consultez le fil des commentaires: github.com/jashkenas/underscore/commit/… - cela peut répondre à cette question.
Rob Grant
41
Y a-t-il eu des efforts pour fusionner le lodash en tiret bas?
lampadaire
186

Lo-Dash est inspiré par le soulignement, mais est aujourd'hui une solution supérieure. Vous pouvez créer vos versions personnalisées , avoir des performances supérieures , prendre en charge AMD et disposer de fonctionnalités supplémentaires intéressantes . Consultez ce benchmark Lo-Dash vs Underscore sur jsperf et .. ce post génial sur lo-dash :

L'une des fonctionnalités les plus utiles lorsque vous travaillez avec des collections est la syntaxe abrégée:

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 }]

(extrait des documents lodash )

neiker
la source
1
Le lien vers le blog de Kit Cambridge est très informatif.
Brian M. Hunt
Je pense que c'est faux (l'exemple de plumaison). Depuis la dernière mise à jour 1.8.3, vous pouvez utiliser pluck de la même manière que lodash. de toute façon pour les versions précédentes, je ne pense pas que le soulignement exposerait une fonction qui est la même une carte (votre exemple de soulignement ressemble à une fonction de carte)
alexserver
7
filtervedette dans le soulignement de 2012 github.com/jashkenas/underscore/issues/648 (son nom est where)
Muhammad Hewedy
Je reçois l'erreur 500 sur le lien de référence Lo-Dash vs Underscore
Hylle
86

Si, comme moi, vous vous attendiez à une liste des différences d'utilisation entre le trait de soulignement et le lodash, il existe un guide pour la migration du trait de soulignement au lodash .

Voici son état actuel pour la postérité:

  • Souligner _.any est Lodash_.some
  • Souligner _.all est Lodash_.every
  • Souligner _.compose est Lodash_.flowRight
  • Souligner _.contains est Lodash_.includes
  • Souligner _.each ne permet pas de quitter en revenantfalse
  • Souligner _.findWhere est Lodash_.find
  • Souligner _.flatten est profond par défaut tandis que Lodash est peu profond
  • Underscore _.groupByprend en charge un itéré qui reçoit les paramètres (value, index, originalArray), tandis que dans Lodash, l'itéré pour _.groupByne reçoit qu'un seul paramètre:(value) .
  • Souligner _.indexOfavec le 3e paramètreundefined est Lodash_.indexOf
  • Souligner _.indexOfavec le 3e paramètretrue est Lodash_.sortedIndexOf
  • Souligner _.indexBy est Lodash_.keyBy
  • Souligner _.invoke est Lodash_.invokeMap
  • Souligner _.mapObject est Lodash_.mapValues
  • Underscore _.maxcombine Lodash_.maxet_.maxBy
  • Underscore _.mincombine Lodash _.minet_.minBy
  • Underscore _.samplecombine Lodash _.sampleet_.sampleSize
  • Underscore _.objectcombine Lodash _.fromPairset_.zipObject
  • Souligner _.omitpar un prédicat est Lodash_.omitBy
  • Underscore_.pairs est Lodash_.toPairs
  • Souligner _.pickpar un prédicat est Lodash_.pickBy
  • Underscore_.pluck est Lodash_.map
  • Underscore _.sortedIndexcombine Lodash _.sortedIndexet_.sortedIndexOf
  • Underscore _.uniqpar an iterateeis Lodash_.uniqBy
  • Underscore_.where est Lodash_.filter
  • Underscore _.isFinitene s'aligne pas Number.isFinite
    (par exemple, _.isFinite('1')retourne truedans Underscore mais falsedans Lodash)
  • Le _.matchesraccourci de soulignement ne prend pas en charge les comparaisons approfondies
    (par exemple _.filter(objects, { 'a': { 'b': 'c' } }))
  • Souligner ≥ 1,7 et la _.templatesyntaxe Lodash est
    _.template(string, option)(data)
  • Les _.memoizecaches Lodash sont Mapcomme des objets
  • Lodash ne supporte pas un contextargument pour de nombreuses méthodes en faveur de_.bind
  • Lodash prend en charge le chaînage implicite , l' enchaînement paresseux, et fusion raccourci
  • Lodash divisé sa surcharge _.head, _.last, _.rest, et _.initialsortir dans
    _.take, _.takeRight, _.drop, & _.dropRight
    (c. - _.head(array, 2)à Souligné est _.take(array, 2)en Lodash)
Iest
la source
1
J'ai moi-même rencontré ces problèmes lors de la migration et je maintiens une documentation croisée (WIP) allant de l'un à l'autre. J'espère que cela sera utile à d'autres personnes également!
luxon
60

En plus de la réponse de John, et en lisant sur lodash (que j'avais jusque-là considéré comme un "moi-aussi" pour souligner), et en voyant les tests de performance, en lisant le code source et les articles de blog , les quelques points qui font lodash sont bien supérieurs à souligner:

  1. Il ne s'agit pas de la vitesse, car il s'agit de la cohérence de la vitesse (?)

    Si vous regardez dans le code source du trait de soulignement, vous verrez dans les premières lignes que le soulignement se replie sur les implémentations natives de nombreuses fonctions. Bien que dans un monde idéal, cela aurait été une meilleure approche, si vous regardez certains des liens de perf donnés dans ces diapositives , il n'est pas difficile de conclure que la qualité de ces `` implémentations natives '' varie beaucoup. au navigateur. Firefox est sacrément rapide dans certaines fonctions, et dans certains Chrome domine. (J'imagine qu'il y aurait des scénarios où IE dominerait aussi). Je pense qu'il vaut mieux préférer un code dont les performances sont plus cohérentes entre les navigateurs.

    Lisez le billet de blog plus tôt, et au lieu de le croire pour lui-même, jugez par vous-même en exécutant les repères . Je suis stupéfait en ce moment, en voyant un lodash effectuer 100-150% plus rapide que underscore même simples , natif des fonctions telles que Array.everyChrome!

  2. Les extras dans lodash sont également très utiles.

  3. En ce qui concerne le commentaire hautement surévalué de Xananax suggérant une contribution au code de soulignement: il est toujours préférable d'avoir une BONNE concurrence, non seulement cela continue l'innovation, mais vous pousse également à vous maintenir (ou votre bibliothèque) en bonne forme.

Voici une liste des différences entre lodash, et sa construction de soulignement est un remplacement direct pour vos projets de soulignement.

kumarharsh
la source
6
Dans quel cas la "cohérence de la vitesse" est-elle une valeur? Disons que j'ai une méthode qui a une vitesse de 100% dans FF et dans IE et une implémentation native aurait une vitesse de 80% dans IE et 120% dans FF (ou l'inverse). Ensuite, je dirais qu'il serait bon d'utiliser l'implémentation native dans FF et la propre implémentation dans IE. Je ne peux imaginer aucun cas, où je dirais: Ralentissons FF juste pour la raison d'avoir la même vitesse là-bas que dans IE. La taille du code et la maintenabilité ou un ralentissement moyen dans tous les navigateurs seraient des arguments, mais la cohérence de la vitesse?
stofl
2
Je voulais dire, "vitesse toujours plus rapide"
kumarharsh
1
Et la différence de taille? Disons que vous créez une construction personnalisée avec lodash qui a exactement les mêmes fonctionnalités que le trait de soulignement? Y a-t-il une grande différence entre eux? Je suppose que la réimplémentation ajoute du poids au site.
F Lekschas
5
Je suis enclin à revenir à l'implémentation native du navigateur simplement parce que dans la plupart des cas, il a des performances acceptables et peut s'améliorer avec les mises à jour du navigateur sans souci de garder la bibliothèque à jour.
orad
3
@KumarHarsh Peut-être que je ne l'ai pas bien formulé. Je voulais dire que je suis enclin à utiliser une bibliothèque qui utilise en interne des fonctions natives si elles sont disponibles, au lieu de toujours préférer sa propre implémentation.
2014 à 14h57
42

Nous sommes en 2014 et quelques années trop tard. Je pense toujours que mon argument est valable:

À mon humble avis, cette discussion a été assez disproportionnée. Citant le billet de blog susmentionné :

La plupart des bibliothèques d'utilitaires JavaScript, telles que Underscore, Valentine et wu, reposent sur la «double approche native-first». Cette approche préfère les implémentations natives, ne retombant dans le JavaScript vanilla que si l'équivalent natif n'est pas pris en charge. Mais jsPerf a révélé une tendance intéressante: la façon la plus efficace d'itérer sur un tableau ou une collection de type tableau est d'éviter complètement les implémentations natives, en optant plutôt pour des boucles simples.

Comme si les "boucles simples" et le "vanilla Javascript" étaient plus natifs que les implémentations de méthodes Array ou Object. Bon sang ...

Ce serait certainement bien d'avoir une seule source de vérité, mais il n'y en a pas. Même si on vous a dit le contraire, il n'y a pas de Dieu vanille, ma chère. Je suis désolé. La seule hypothèse qui tient vraiment est que nous écrivons tous du code Javascript qui vise à bien fonctionner dans tous les principaux navigateurs, sachant que tous ont des implémentations différentes des mêmes choses. C'est une chienne à gérer, pour le moins. Mais c'est la prémisse, que cela vous plaise ou non.

Peut-être que vous travaillez tous sur des projets à grande échelle qui nécessitent des performances Twitterish afin que vous puissiez vraiment voir la différence entre 850 000 (soulignement) et 2 500 000 (lodash) itérations sur une liste par seconde en ce moment!

Pour ma part, je ne le suis pas. Je veux dire, j'ai travaillé sur des projets où je devais résoudre des problèmes de performances, mais ils n'ont jamais été résolus ou causés par ni Underscore ni Lo-Dash. Et à moins que je ne comprenne les vraies différences d'implémentation et de performances (nous parlons en ce moment de C ++) de disons une boucle sur un itérable (objet ou tableau, clairsemé ou non!), Je ne me soucie pas du tout des revendications basées sur les résultats d'une plateforme de référence déjà jugée .

Il n'a besoin que d'une seule mise à jour de, disons Rhino, pour mettre le feu à ses implémentations de méthode Array d'une manière qu'aucun prêtre "des méthodes de boucle médiévales ne fonctionne mieux et pour toujours et ainsi de suite". une méthode de tableau soudaine dans FF est beaucoup plus rapide que son brainfuck opiniâtre. Man, vous ne pouvez tout simplement pas tromper votre environnement d'exécution en trichant votre environnement d'exécution! Pensez-y lorsque vous faites la promotion ...

votre ceinture utilitaire

... la prochaine fois.

Donc, pour rester pertinent:

  • Utilisez Underscore si vous préférez sans sacrifier l'isch natif.
  • Utilisez Lo-Dash si vous aimez la commodité et aimez son catalogue de fonctionnalités étendu (copie complète, etc.) et si vous avez désespérément besoin de performances instantanées et, surtout, cela ne vous dérange pas de vous contenter d'une alternative dès que l'API native est dépassée contournements d'opinion. Ce qui va arriver bientôt. Période.
  • Il y a même une troisième solution. DIY! Connaissez vos environnements. Connaître les incohérences. Lisez leur code ( John-David et Jeremy ). N'utilisez pas ceci ou cela sans être en mesure d'expliquer pourquoi une couche de cohérence / compatibilité est vraiment nécessaire et améliore votre flux de travail ou améliore les performances de votre application. Il est très probable que vos exigences soient satisfaites avec une simple polyfill que vous êtes parfaitement capable d'écrire vous-même. Les deux bibliothèques sont tout simplement de la vanille avec un peu de sucre. Ils se battent tous les deux pour savoir qui sert la tarte la plus sucrée . Mais croyez-moi, au final, les deux ne font que cuisiner avec de l'eau. Il n'y a pas de dieu vanille donc il ne peut pas y avoir de pape vanille, non?

Choisissez l'approche qui correspond le mieux à vos besoins. Comme d'habitude. Je préfère les solutions de repli sur les implémentations réelles aux tricheurs d'exécution d'opinion à tout moment, mais même cela semble être une question de goût de nos jours. Restez fidèle à des ressources de qualité comme http://developer.mozilla.com et http://caniuse.com et tout ira bien.

Lukas Bünger
la source
Merci d'avoir posté Lukas. Les intégrés peuvent-ils être encore optimisés? J'en déduis qu'ils ont des contraintes imposées par les normes qui les empêchent d'avoir des optimisations comparables aux bibliothèques, mais je ne connais pas les détails par hasard ou si c'était ou reste vrai.
Brian M. Hunt du
par exemple "En optimisant pour le cas d'utilisation à 99%, les méthodes fast.js peuvent être jusqu'à 5 fois plus rapides que leurs équivalents natifs." - github.com/codemix/fast.js
Brian M. Hunt
1
Salut Brian, je suis désolé si cela était trompeur, je ne voulais pas dire que ces bibliothèques ne sont pas beaucoup plus rapides que leurs équivalents natifs. Si vous avez désespérément besoin de performances en ce moment , vous êtes probablement mieux avec une boîte à outils comme LoDash ou fast.js car ils fournissent des implémentations plus rapides des méthodes standard. Mais si vous choisissez d'utiliser une bibliothèque qui ne retombe pas sur des méthodes natives, vous risquez de passer à côté de toute optimisation des performances future sur les intégrés. Les navigateurs évolueront éventuellement.
Lukas Bünger
4
Les «fabricants» de navigateurs ont du mal à maintenir les normes de leurs navigateurs conformes, et encore moins performantes. La plupart des gains de performances dans les implémentations natives sont le résultat d'un matériel plus rapide. L'excuse «les implémentations natives rattraperont» existe depuis des années. Années = éternité sur Internet. Si les implémentations natives rattrapent leur retard, les bibliothèques seront mises à jour pour les utiliser. C'est ce qui est cool avec l'open source. Si un développeur d'application ne se met pas à jour vers la dernière bibliothèque, son application ne ralentira pas soudainement, elle n'accélèrera tout simplement pas.
Andrew Steitz
2
... mais si vous leur posiez des questions, Array.fromils ne sauraient probablement même pas ce que cela est censé faire. Les gens de la «ceinture utilitaire» JS semblent tellement préoccupés par la promotion de leurs solutions de contournement si géniales qu'ils ont tendance à oublier qu'en agissant ainsi, ils diluent en fait le processus de normalisation. Aucun besoin de fonctionnalités n'entraîne de pression sur les "fabricants" de navigateurs. Fait amusant: 2 des 4 principaux navigateurs sont basés sur des projets open source ( 1 , 2 ).
Lukas Bünger
20

Je suis d'accord avec la plupart des choses dites ici mais je veux juste souligner un argument en faveur de underscore.js: la taille de la bibliothèque.

Surtout dans le cas où vous développez une application ou un site Web destiné à être utilisé principalement sur des appareils mobiles, la taille du bundle résultant et l'effet sur le démarrage ou le temps de téléchargement peuvent avoir un rôle important.

À titre de comparaison, ces tailles sont celles que j'ai remarquées avec source-map-explorer après avoir exécuté le service ionique:

lodash: 523kB
underscore.js: 51.6kb

édité en février 2020 :

on peut utiliser BundlePhobia pour vérifier la taille actuelle de Lo-Dash et Underscore

David Dal Busco
la source
1
Merci Peter, c'est un point intéressant à noter ici. Il y a plus de discussion ailleurs, y compris: gist.github.com/alekseykulikov/5f4a6ca69e7b4ebed726 . (Cette réponse pourrait être améliorée en reliant certaines des autres discussions et en citant les bits pertinents) La différence de taille peut être réduite en choisissant des sous-sections de lodash, plus lodash secouant les arbres. 🕷
Brian M. Hunt
Thx @ BrianM.Hunt pour votre réponse, ne savait pas qu'il est possible d'inclure des sous-sections de lodash, va y jeter un œil. Récemment, avec ionic-native, Ionic a pris un tel chemin aussi pour leurs bibliothèques natives, bon de noter que de plus en plus sont préoccupés par la taille de l'application
David Dal Busco
1
je me demande où avez-vous obtenu le 523kB? lodash.com indique qu'il n'est compressé qu'à 24 Ko. téléchargé est seulement 74kB
Martian2049
1
mon message a été fait en avril 2017. comme je l'ai dit dans mon commentaire,source-map-explorer after running ionic serve
David Dal Busco
5
En mars 2018 - lodash.min.js est de 72,5 ko et underscore-min.js est de 16,4 ko
Combinez
10

Je ne sais pas si c'est ce que OP voulait dire, mais je suis tombé sur cette question parce que je cherchais une liste de problèmes que je dois garder à l'esprit lors de la migration du trait de soulignement vers lodash.

J'apprécierais vraiment que quelqu'un publie un article avec une liste complète de ces différences. Permettez-moi de commencer par les choses que j'ai apprises à la dure (c'est-à-dire les choses qui ont fait exploser mon code en production: /):

  • _.flattendans le soulignement est profond par défaut et vous devez passer true comme deuxième argument pour le rendre superficiel. Dans lodash, il est peu profond par défaut et passe vrai car le deuxième argument le rendra profond! :)
  • _.lasten trait de soulignement accepte un deuxième argument qui indique combien d'éléments vous voulez. Il lodashn'y a pas une telle option. Vous pouvez imiter cela avec.slice
  • _.first (même problème)
  • _.templatedans le trait de soulignement peut être utilisé de plusieurs façons, dont l'une fournit la chaîne et les données du modèle et HTMLrécupère (ou du moins c'est ainsi que cela fonctionnait il y a quelque temps). En lodashvous recevez une fonction que vous devriez alors alimenter avec les données.
  • _(something).map(foo)fonctionne en soulignement, mais en lodash j'ai dû le réécrire _.map(something,foo). C'était peut-être juste un TypeScriptproblème
qbolec
la source
4
Dans lodash, le chaînage passe par un itérateur paresseux, et nécessite et un point de terminaison comme _(something).map(foo).value().
Brian M. Hunt
Tout cela peut vous toucher si vous utilisez Backbone Collection qui procède à des appels par proxy à ces bibliothèques - par exemple collection.first (5) ne vous donnera pas les 5 premiers éléments, mais plutôt le premier :)
qbolec
8

http://benmccormick.org/2014/11/12/underscore-vs-lodash/

Dernier article comparant les deux de Ben McCormick:

  1. L'API de Lo-Dash est un surensemble de Underscore.

  2. Sous le capot [Lo-Dash] a été complètement réécrit.

  3. Lo-Dash n'est certainement pas plus lent que Underscore.

  4. Qu'a ajouté Lo-Dash?

    • Améliorations de l'utilisabilité
    • Fonctionnalité supplémentaire
    • Gains de performance
    • Syntaxes abrégées pour le chaînage
    • Constructions personnalisées pour utiliser uniquement ce dont vous avez besoin
    • Versioning sémantique et couverture de code à 100%
pilaf
la source
6

Je viens de découvrir une différence qui a fini par être importante pour moi. La version non compatible avec le soulignement de lodash _.extend()ne copie pas les propriétés ou méthodes définies au niveau de la classe.

J'ai créé un test Jasmine dans CoffeeScript qui le démontre:

https://gist.github.com/softcraft-development/1c3964402b099893bd61

Heureusement, lodash.underscore.jspréserve le comportement d'Underscore de tout copier, ce qui, pour ma situation, était le comportement souhaité.

Craig Walker
la source
4

lodash a obtenu _.mapValues()qui est identique à underescore _.mapObject().

artknight
la source
0

Pour la plupart, le soulignement est un sous-ensemble de lodash. Parfois, comme actuellement le soulignement aura de petites fonctions sympas que lodash n'a pas comme mapObject. Celui-ci m'a fait gagner beaucoup de temps dans le développement de mon projet.

rashadb
la source
à l'époque, nous avons _.mapValues
crapthings
@crapthings - au moment de cette publication, je connaissais mayValues ​​et mapKeys mais ce n'est pas la même chose que mapObject. Il y a peut-être des cas à appliquer l'un sur l'autre, mais mapObject est une fonction qui lui est propre.
rashadb
0

Ils sont assez similaires, avec Lodash prend le relais ...

Ils sont tous deux une bibliothèque d'utilitaires qui prend le monde de l'utilité en JavaScript ...

Il semble que Lodash soit mis à jour plus régulièrement maintenant, donc plus utilisé dans les derniers projets ...

Aussi Lodash semble est plus léger par un couple de KBS ...

Les deux ont une bonne api et doc, mais je pense que Lodash est meilleur ...

Voici une capture d'écran pour chacun des documents pour obtenir la première valeur d'un tableau ...

souligner:

souligner

lodash: lodash

Comme les choses peuvent être mises à jour de temps en temps, il suffit de consulter leur site Web également ...

lodash

souligner

Alireza
la source