Diferencias entre lodash y subrayado [cerrado]

1602

¿Por qué alguien preferiría la biblioteca de utilidad lodash.js o underscore.js sobre la otra?

Lodash parece ser un reemplazo directo para el guión bajo, este último ha existido por más tiempo.

Creo que ambos son brillantes, pero no sé lo suficiente sobre cómo funcionan para hacer una comparación educada, y me gustaría saber más sobre las diferencias.

Brian M. Hunt
fuente
2
Es posible que desee echar un vistazo a algunos de los lanzamientos de pantalla sobre lodash que están vinculados en su página de github. Personalmente, he estado usando underscore.js, pero más porque eso es con lo que comencé y, como dices, ha existido por más tiempo.
Jack
26
lodashy underscoreestán bajo hilo de fusión ahora
zangw

Respuestas:

2023

Creé Lo-Dash para proporcionar una compatibilidad de iteración entre entornos más coherente para matrices, cadenas, objetos y argumentsobjetos 1 . Desde entonces se ha convertido en un superconjunto de Underscore, proporcionando un comportamiento API más consistente, más funciones (como soporte AMD, clonación profunda y fusión profunda), documentación más exhaustiva y pruebas unitarias (pruebas que se ejecutan en Node, Ringo, Rhino, Narwhal, PhantomJS y navegadores), un mejor rendimiento general y optimizaciones para matrices grandes / iteración de objetos, y más flexibilidad con compilaciones personalizadas y utilidades de precompilación de plantillas.

Debido a que Lo-Dash se actualiza con más frecuencia que Underscore, se proporciona una lodash underscorecompilación para garantizar la compatibilidad con la última versión estable de Underscore.

En un momento, incluso me dieron acceso push a Underscore, en parte porque Lo-Dash es responsable de plantear más de 30 problemas; soluciones de errores de aterrizaje, nuevas características y ganancias de rendimiento en Underscore v1.4.x +.

Además, hay al menos 3 repeticiones de Backbone que incluyen Lo-Dash por defecto y Lo-Dash ahora se menciona en la documentación oficial de Backbone .

Mira la publicación de Kit Cambridge, Di "Hola" a Lo-Dash , para un desglose más profundo sobre las diferencias entre Lo-Dash y Underscore.

Notas al pie:

  1. El subrayado es incompatible con matrices, cadenas, objetos y argumentsobjetos. En los navegadores más nuevos, los métodos de subrayado ignoran los agujeros en las matrices , los métodos de "Objetos" iteran argumentsobjetos, las cadenas se tratan como una matriz y los métodos iteran correctamente las funciones (ignorando su propiedad "prototipo") y los objetos (iterando propiedades sombreadas como "toString" y "valueOf"), mientras que en navegadores más antiguos no lo harán. Además, los métodos de subrayado como _.clonepreservar agujeros en matrices, mientras que otros _.flattenno.
John-David Dalton
fuente
174
@Brian - Mientras desarrollaba Lo-Dash, seguí haciendo la pregunta "¿Qué podría señalar alguien, en Lo-Dash, como negativo en comparación con el subrayado?" y luego abordarlos. Es por eso que he reforzado la documentación, agregado compilaciones personalizadas y hecho que la fuente sea más legible.
John-David Dalton
10
Estoy muy tentado a publicar algunos puntos de referencia, pero eso podría volverse tedioso. Baste decir que cada punto de referencia que he ejecutado ha demostrado que Lo-Dash es más rápido ( MUCHO más rápido en muchos casos) que el subrayado.
Wil Moore III
186
Me encanta lo-dash y lo estoy usando, así que, por favor, no creas que estoy criticando, pero ¿por qué no contribuir a subrayar en lugar de crear una nueva biblioteca?
Xananax
133
@ Xananax - revise el hilo de comentarios: github.com/jashkenas/underscore/commit/… - esto puede responder esa pregunta.
Rob Grant
41
¿Ha habido algún esfuerzo por fusionar lodash nuevamente en guión bajo?
farola
186

Lo-Dash está inspirado en el guión bajo, pero hoy en día es una solución superior. Puede realizar sus compilaciones personalizadas , tener un mayor rendimiento , admitir AMD y tener excelentes funciones adicionales . Comprueba estos puntos de referencia Lo-Dash vs Underscore en jsperf y ... esta impresionante publicación sobre lo-dash :

Una de las características más útiles cuando trabaja con colecciones es la sintaxis abreviada:

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

(tomado de lodash docs )

neiker
fuente
1
El enlace al blog de Kit Cambridge es muy informativo.
Brian M. Hunt
Creo que esto está mal (el ejemplo de arrancar). A partir de la última actualización 1.8.3, puede usar pluck de la misma manera que lodash. de todos modos para versiones anteriores, no creo que el subrayado exponga una función que sea igual a un mapa (su ejemplo de subrayado parece una función de mapa)
alexserver
77
filteren subrayado de 2012 github.com/jashkenas/underscore/issues/648 (su nombre es where)
Muhammad Hewedy
Recibo el error 500 en el enlace de referencia Lo-Dash vs Underscore
Hylle
86

Si, como yo, esperaba una lista de diferencias de uso entre subrayado y lodash, hay una guía para migrar de subrayado a lodash .

Aquí está el estado actual de la posteridad:

  • El _.anyguión bajo es Lodash_.some
  • El _.allguión bajo es Lodash_.every
  • El _.composeguión bajo es Lodash_.flowRight
  • El _.containsguión bajo es Lodash_.includes
  • El subrayado _.eachno permite salir regresandofalse
  • El _.findWhereguión bajo es Lodash_.find
  • El subrayado _.flattenes profundo por defecto, mientras que Lodash es superficial
  • Subrayado _.groupBysoporta un iteratee que se pasa los parámetros (value, index, originalArray), mientras que en Lodash, la iteratee para _.groupBysolamente se pasa un único parámetro: (value).
  • El subrayado _.indexOfcon el tercer parámetro undefinedes Lodash_.indexOf
  • El subrayado _.indexOfcon el tercer parámetro truees Lodash_.sortedIndexOf
  • El _.indexByguión bajo es Lodash_.keyBy
  • El _.invokeguión bajo es Lodash_.invokeMap
  • El _.mapObjectguión bajo es Lodash_.mapValues
  • El _.maxsubrayado combina Lodash _.maxy_.maxBy
  • El _.minsubrayado combina Lodash _.miny_.minBy
  • El _.samplesubrayado combina Lodash _.sampley_.sampleSize
  • El _.objectsubrayado combina Lodash _.fromPairsy_.zipObject
  • El subrayado _.omitde un predicado es Lodash_.omitBy
  • El _.pairsguión bajo es Lodash_.toPairs
  • El subrayado _.pickde un predicado es Lodash_.pickBy
  • El _.pluckguión bajo es Lodash_.map
  • El _.sortedIndexsubrayado combina Lodash _.sortedIndexy_.sortedIndexOf
  • Subrayado _.uniqpor un iterateees Lodash_.uniqBy
  • El _.whereguión bajo es Lodash_.filter
  • El subrayado _.isFiniteno se alinea con Number.isFinite
    (por ejemplo, _.isFinite('1')devuelve en subrayado truepero falseen Lodash)
  • La _.matchestaquigrafía de subrayado no admite comparaciones profundas
    (por ejemplo _.filter(objects, { 'a': { 'b': 'c' } }))
  • Subrayado ≥ 1.7 y la _.templatesintaxis de Lodash es
    _.template(string, option)(data)
  • Los _.memoizecachés de Lodash son Mapcomo objetos
  • Lodash no admite contextargumentos para muchos métodos a favor de_.bind
  • Lodash admite el encadenamiento implícito , el encadenamiento perezoso y la fusión de atajos
  • Lodash divide su sobrecargado _.head, _.last, _.rest, y _.initialhacia fuera en
    _.take, _.takeRight, _.drop, y _.dropRight
    (es decir, _.head(array, 2)en subrayado es _.take(array, 2)en Lodash)
Iest
fuente
1
Me encontré con estos problemas al migrar y mantengo una documentación cruzada (WIP) entre uno y otro. ¡Espero que también sea útil para otras personas!
luxon
60

Además de la respuesta de John, y leer sobre lodash (que hasta ahora había considerado como un "yo también" para subrayar), y ver las pruebas de rendimiento, leer el código fuente y las publicaciones de blog , los pocos puntos que hacen lodash Estos son muy superiores al guión bajo:

  1. No se trata de la velocidad, ya que se trata de la consistencia de la velocidad (?)

    Si observa el código fuente de subrayado, verá en las primeras líneas que el subrayado recurre a las implementaciones nativas de muchas funciones. Aunque en un mundo ideal, este habría sido un mejor enfoque, si observa algunos de los enlaces de rendimiento proporcionados en estas diapositivas , no es difícil llegar a la conclusión de que la calidad de esas 'implementaciones nativas' varía mucho en el navegador. al navegador Firefox es muy rápido en algunas de las funciones, y en algunas domina Chrome. (Me imagino que habría algunos escenarios en los que IE también dominaría). Creo que es mejor preferir un código cuyo rendimiento sea ​​más consistente en todos los navegadores.

    Lea la publicación del blog anteriormente, y en lugar de creerlo por sí mismo, juzgue por usted mismo ejecutando los puntos de referencia . Estoy aturdido en este momento, al ver un lodash realización de 100-150% más rápido que en el guión bajo, incluso sencilla , nativos funciones como Array.everyen Chrome!

  2. Los extras en lodash también son bastante útiles.

  3. En cuanto al comentario altamente votado de Xananax que sugiere una contribución al código de subrayado: siempre es mejor tener una BUENA competencia, no solo mantiene la innovación, sino que también te impulsa a mantenerte (o tu biblioteca) en buena forma.

Aquí hay una lista de diferencias entre lodash, y su subrayado-construcción es un reemplazo directo para sus proyectos de subrayado.

kumarharsh
fuente
66
¿En qué caso es un valor la "consistencia de la velocidad"? Digamos que tengo un método que tiene una velocidad del 100% en FF y en IE y una implementación nativa tendría una velocidad del 80% en IE y 120% en FF (o al revés). Entonces diría que sería bueno usar la implementación nativa en FF y la propia implementación en IE. No puedo imaginar ningún caso en el que yo diría: reduzcamos la velocidad de FF solo por el motivo de tener la misma velocidad que en IE. El tamaño del código y la capacidad de mantenimiento o una desaceleración promedio en todos los navegadores serían argumentos, pero ¿consistencia en la velocidad?
stofl
2
Me refiero, "consistentemente más rápido de velocidad"
kumarharsh
1
¿Qué pasa con la diferencia de tamaño? Supongamos que crea una compilación personalizada con lodash que tiene exactamente la misma funcionalidad que el subrayado. ¿Hay una gran diferencia entre ellos? Supongo que la reimplementación agrega peso al sitio.
F Lekschas
55
Me inclino a recurrir a la implementación nativa del navegador simplemente porque en la mayoría de los casos tiene un rendimiento aceptable y puede mejorar con las actualizaciones del navegador sin preocuparse de mantener la biblioteca actualizada.
orad
3
@ KumarHarsh Tal vez no lo expresé bien. Quise decir que estoy inclinado a usar una biblioteca que internamente use funciones nativas si están disponibles, en lugar de preferir siempre su propia implementación.
orad
42

Esto es 2014 y un par de años demasiado tarde. Todavía creo que mi punto es válido:

En mi humilde opinión, esta discusión se volvió bastante desproporcionada. Citando la publicación del blog antes mencionada :

La mayoría de las bibliotecas de utilidades de JavaScript, como Underscore, Valentine y wu, se basan en el "enfoque dual nativo-primero". Este enfoque prefiere implementaciones nativas, recurriendo a JavaScript vainilla solo si el equivalente nativo no es compatible. Pero jsPerf reveló una tendencia interesante: la forma más eficiente de iterar sobre una matriz o colección tipo matriz es evitar las implementaciones nativas por completo, optando por bucles simples.

Como si "bucles simples" y "Javascript vainilla" fueran más nativos que las implementaciones de métodos Array u Object. Dios ...

Ciertamente sería bueno tener una sola fuente de verdad, pero no la hay. Incluso si te han dicho lo contrario, no hay Dios de vainilla, querida. Lo siento. La única suposición que realmente se cumple es que todos estamos escribiendo código Javascript que tiene como objetivo un buen desempeño en todos los principales navegadores, sabiendo que todos ellos tienen implementaciones diferentes de las mismas cosas. Es una perra con la que lidiar, por decirlo suavemente. Pero esa es la premisa, te guste o no.

¡Quizás estén trabajando en proyectos a gran escala que necesitan un rendimiento de Twitter para que realmente vean la diferencia entre 850,000 (subrayado) y 2,500,000 (lodash) iteraciones en una lista por segundo en este momento!

Yo por mi parte no lo soy. Quiero decir, trabajé en proyectos donde tenía que abordar problemas de rendimiento, pero nunca fueron resueltos ni causados ​​por Underscore ni Lo-Dash. Y a menos que comprenda las diferencias reales en la implementación y el rendimiento (estamos hablando de C ++ en este momento) de, digamos, un bucle sobre un iterable (objeto o matriz, disperso o no), prefiero no molestarme con ninguno afirmaciones basadas en los resultados de una plataforma de referencia que ya es obstinada .

Solo necesita una única actualización de, digamos, Rhino para prender fuego a sus implementaciones de métodos Array de tal manera que ni un solo "método de bucle medieval funcione mejor y para siempre", y el sacerdote puede discutir sobre el simple hecho de que todos Los métodos de matriz repentina en FF son mucho más rápidos que su mentalidad obstinada. Hombre, ¡no puedes engañar a tu entorno de ejecución engañando a tu entorno de ejecución! Piensa en eso al promocionar ...

su cinturón utilitario

... la próxima vez.

Entonces, para mantenerlo relevante:

  • Utilice el subrayado si le gusta la comodidad sin sacrificar el ish nativo.
  • Use Lo-Dash si le gusta la comodidad y le gusta su catálogo extendido de características (copia profunda, etc.) y si necesita desesperadamente un rendimiento instantáneo y lo más importante no le importa conformarse con una alternativa tan pronto como la API nativa eclipse obstinados fondos de trabajo. Lo que va a suceder pronto. Período.
  • Incluso hay una tercera solución. Bricolaje! Conoce tus ambientes. Sepa sobre inconsistencias. Lea su código (de John-David y Jeremy ). No use esto o aquello sin poder explicar por qué una capa de consistencia / compatibilidad es realmente necesaria y mejora su flujo de trabajo o el rendimiento de su aplicación. Es muy probable que sus requisitos se cumplan con un simple polyfill que puede escribir usted mismo perfectamente. Ambas bibliotecas son simplemente vainilla con un poco de azúcar. Ambos pelean por quién sirve el pastel más dulce . Pero créanme, al final ambos solo están cocinando con agua. No hay Dios de vainilla, así que no puede haber papa de vainilla, ¿verdad?

Elija el enfoque que mejor se adapte a sus necesidades. Como siempre. Preferiría fallos en implementaciones reales en lugar de trucos de tiempo de ejecución obstinados en cualquier momento, pero incluso eso parece ser cuestión de gustos hoy en día. Apéguese a recursos de calidad como http://developer.mozilla.com y http://caniuse.com y estará bien.

Lukas Bünger
fuente
Gracias por publicar Lukas. ¿Se pueden optimizar aún más las funciones integradas? Llegué a la conclusión de que tienen restricciones impuestas por los estándares que les impiden tener optimizaciones comparables a las bibliotecas, pero no conozco los detalles de forma espontánea o si esto fue o sigue siendo cierto.
Brian M. Hunt
por ejemplo, "Al optimizar para el caso de uso del 99%, los métodos fast.js pueden ser hasta 5 veces más rápidos que sus equivalentes nativos". - github.com/codemix/fast.js
Brian M. Hunt
1
Hola Brian, lo siento si esto fue engañoso, no quise decir que esas bibliotecas no son mucho más rápidas que sus equivalentes nativos. Si necesita desesperadamente rendimiento en este momento , probablemente esté mejor con un kit de herramientas como LoDash o fast.js, ya que proporcionan implementaciones más rápidas de métodos estándar. Pero si elige usar una biblioteca que no recurra a los métodos nativos, es posible que se pierda las optimizaciones de rendimiento futuras en las incorporadas. Los navegadores evolucionarán eventualmente.
Lukas Bünger
44
Los "fabricantes" de navegadores tienen dificultades para mantener el cumplimiento de los estándares de sus navegadores, y mucho menos su rendimiento. La mayoría de las ganancias de rendimiento en las implementaciones nativas son el resultado de un hardware más rápido. La excusa "las implementaciones nativas se pondrán al día" ha existido durante años. Años = eternidad en internet. SI las implementaciones nativas alguna vez se ponen al día, las bibliotecas se actualizarán para usarlas. Eso es lo bueno del código abierto. Si un desarrollador de aplicaciones no se actualiza a la última biblioteca, su aplicación no se ralentizará repentinamente, simplemente no se acelerará.
Andrew Steitz el
2
... pero si les preguntaras sobre Array.fromellos, probablemente ni siquiera sabrían lo que se supone que debe hacer. La gente del "cinturón de servicios" de JS parece estar demasiado preocupada con la promoción de sus soluciones tan geniales que tienden a olvidar que al hacerlo, en realidad están diluyendo el proceso de estandarización. La ausencia de funciones no genera presión sobre los "fabricantes" del navegador. Dato curioso: 2 de los 4 principales navegadores se basan en proyectos de código abierto ( 1 , 2 ).
Lukas Bünger
20

Estoy de acuerdo con la mayoría de las cosas que se dicen aquí, pero solo quiero señalar un argumento a favor de underscore.js: el tamaño de la biblioteca.

Especialmente en caso de que esté desarrollando una aplicación o sitio web que pretenda utilizar principalmente en dispositivos móviles, el tamaño del paquete resultante y el efecto en el tiempo de arranque o descarga pueden tener un papel importante.

A modo de comparación, estos tamaños son los que noté con source-map-explorer después de ejecutar el servicio iónico:

lodash: 523kB
underscore.js: 51.6kb

editado en febrero de 2020 :

uno puede usar BundlePhobia para verificar el tamaño actual de Lo-Dash y subrayado

David Dal Busco
fuente
1
Gracias Peter, este es un punto que vale la pena señalar aquí. Hay más discusión en otro lugar, incluyendo: gist.github.com/alekseykulikov/5f4a6ca69e7b4ebed726 . (Esta respuesta podría mejorarse vinculando algunas de las otras discusiones y citando los bits relevantes) La diferencia de tamaño puede reducirse eligiendo subsecciones de lodash, más lodash que sacude los árboles. 🕷
Brian M. Hunt
Thx @ BrianM. Busque su respuesta, no sabía que es posible incluir subsecciones de lodash, voy a echar un vistazo. Recientemente, con iónico-nativo, Ionic tomó ese camino también para sus bibliotecas nativas, es bueno notar que cada vez más están preocupados por el tamaño de la aplicación
David Dal Busco
1
Me pregunto de dónde sacaste los 523kB. lodash.com dice que solo tiene 24kB comprimido. descargado es solo 74kB
Martian2049
1
mi publicación se realizó en abril de 2017. como dije en mi comentario,source-map-explorer after running ionic serve
David Dal Busco el
55
En marzo de 2018 - lodash.min.js es 72,5 kB y subrayado-min.js es 16,4 kB
Combine
10

No estoy seguro de si eso es lo que OP quiso decir, pero me encontré con esta pregunta porque estaba buscando una lista de problemas que debo tener en cuenta al migrar de subrayado a lodash.

Realmente agradecería si alguien publicara un artículo con una lista completa de tales diferencias. Permítanme comenzar con las cosas que aprendí por las malas (es decir, cosas que hicieron que mi código explotara en producción: /):

  • _.flattenen guión bajo es profundo de forma predeterminada y debe pasar verdadero como segundo argumento para hacerlo superficial. En lodash es poco profundo por defecto y pasar verdadero como segundo argumento lo hará más profundo! :)
  • _.lasten guión bajo acepta un segundo argumento que indica cuántos elementos desea. En lodashno hay tal opción. Puedes emular esto con.slice
  • _.first (mismo problema)
  • _.templateen subrayado se puede usar de muchas maneras, una de las cuales es proporcionar la cadena de plantilla y los datos y HTMLvolver (o al menos así fue como funcionó hace algún tiempo). Enlodash usted recibe una función que luego debe alimentar con los datos.
  • _(something).map(foo)funciona en guión bajo, pero en lodash tuve que reescribirlo _.map(something,foo). Quizás eso fue solo un TypeScriptproblema
qbolec
fuente
44
En lodash, el encadenamiento pasa un iterador perezoso, y requiere un punto final como _(something).map(foo).value().
Brian M. Hunt
Todo esto puede golpearlo si usa Backbone Collection, que representa llamadas a estas bibliotecas, por ejemplo collection.first (5) no le dará los primeros 5 elementos, sino el primero :)
qbolec
8

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

Último artículo comparando los dos de Ben McCormick:

  1. La API de Lo-Dash es un superconjunto de Underscore.

  2. Debajo del capó [Lo-Dash] ha sido completamente reescrito.

  3. Lo-Dash definitivamente no es más lento que el subrayado.

  4. ¿Qué ha agregado Lo-Dash?

    • Mejoras de usabilidad
    • Funcionalidad extra
    • Ganancias de rendimiento
    • Sintaxis abreviada para encadenar
    • Construcciones personalizadas para usar solo lo que necesita
    • Versiones semánticas y cobertura de código 100%
pilau
fuente
6

Acabo de encontrar una diferencia que terminó siendo importante para mí. La versión no-guión-compatibles de lodash de _.extend()hace no copia sobre propiedades o métodos de clase de nivel definidas.

He creado una prueba de Jasmine en CoffeeScript que demuestra esto:

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

Afortunadamente, lodash.underscore.jsconserva el comportamiento de Underscore de copiar todo, que para mi situación era el comportamiento deseado.

Craig Walker
fuente
4

Lodash tiene lo _.mapValues()que es idéntico a la puntuación baja _.mapObject().

artknight
fuente
0

En su mayor parte, el guión bajo es un subconjunto de lodash. A veces, como el subrayado actual tendrá pequeñas funciones geniales, lodash no tiene como mapObject. Este me ahorró mucho tiempo en el desarrollo de mi proyecto.

rashadb
fuente
en ese momento, tenemos _.mapValues
crapthings
@crapthings: en el momento de esta publicación, conocía mayValues ​​y mapKeys, pero no son lo mismo que mapObject. Quizás haya casos para aplicar uno sobre el otro, pero mapObject es una función propia.
rashadb
0

Son bastante similares, con Lodash está haciendo cargo ...

Ambos son una biblioteca de utilidad que toma el mundo de la utilidad en JavaScript ...

Parece que Lodash se está actualizando más regularmente ahora, por lo que se usa más en los últimos proyectos ...

También Lodash parece ser más ligero por un par de KB ...

Ambos tienen una buena api y doc, pero creo que Lodash es mejor ...

Aquí hay una captura de pantalla para cada uno de los documentos para obtener el primer valor de una matriz ...

guion bajo:

guion bajo

lodash: lodash

Como las cosas pueden actualizarse de vez en cuando, solo revise su sitio web también ...

lodash

guion bajo

Alireza
fuente