Diferenças entre lodash e sublinhado

Por que alguém preferiria a biblioteca de utilitários lodash.js ou underscore.js sobre a outra?

Lodash parece ser um substituto para sublinhado, o último tendo sido em torno de mais tempo.

Eu acho que ambos são shinys, mas eu não sei o suficiente sobre como eles funcionam para fazer uma comparação educada, e gostaria de saber mais sobre as diferenças.

   

Eu criei o Lo-Dash para fornecer suporte de iteração cruzada de ambiente mais consistente para arrays, strings, objects e objects de arguments 1 . Desde então, tornou-se um superconjunto do Underscore, fornecendo um comportamento de API mais consistente, mais resources (como suporte a AMD, deep clone e deep merge), documentação mais completa e testes unitários (testes em Node, Ringo, Rhino, Narwhal, PhantomJS e navegadores), melhor desempenho geral e otimizações para grandes arrays / iteração de objects e mais flexibilidade com compilações personalizadas e utilitários de pré-compilation de modelos.

Como o Lo-Dash é atualizado com mais frequência do que o Underscore, uma lodash underscore é fornecida para garantir a compatibilidade com a última versão estável do Underscore.

Em um certo ponto, eu recebi até mesmo o push para Underscore, em parte porque Lo-Dash é responsável por levantar mais de 30 números; Correção de erros de aterrissagem, novos resources e ganhos do perf em Underscore v1.4.x +.

Além disso, há pelo menos três boilerplates do Backbone que incluem Lo-Dash por padrão e Lo-Dash agora é mencionado na documentação oficial do Backbone.

Confira o post do Kit Cambridge, Diga “Olá” para Lo-Dash , para uma análise mais profunda das diferenças entre Lo-Dash e Underscore.

Notas de rodapé:

  1. O sublinhado tem suporte inconsistente para arrays, seqüências de caracteres, objects e objects de arguments . Em navegadores mais novos, os methods Underscore ignoram falhas em arrays , methods “Objects” iteram objects de arguments , strings são tratados como array e methods iteram funções corretamente (ignorando sua propriedade “prototype”) e objects (iterando propriedades sombreadas como “toString” e “valueOf”), enquanto em navegadores mais antigos eles não. Além disso, os methods Underscore, como _.clone preservam os buracos nas matrizes, enquanto outros, como _.flatten , não.

Lo-Dash é inspirado pelo sublinhado, mas hoje em dia é uma solução superior. Você pode fazer suas construções personalizadas , ter um desempenho mais alto , oferecer suporte à AMD e ter ótimos resources extras . Confira este benchmark Lo-Dash vs Underscore no jsperf e .. este post incrível sobre lo-dash :

Um dos resources mais úteis quando você trabalha com collections é a syntax 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 }] 

(retirado da lodash docs )

Além da resposta de John, e lendo sobre o lodash (que eu até então tinha considerado como “eu-também” para sublinhar), e vendo os testes de desempenho, lendo o código-fonte e posts , os poucos pontos que fazem lodash muito superior ao sublinhado são estes:

  1. Não é sobre a velocidade, como é sobre a consistência da velocidade (?)

    Se você olhar para o código-fonte do sublinhado, verá nas primeiras linhas que o sublinhado recai sobre as implementações nativas de muitas funções. Embora em um mundo ideal, essa teria sido uma abordagem melhor, se você olhar para alguns dos links perf indicados nesses slides , não é difícil tirar a conclusão de que a qualidade dessas ‘implementações nativas’ varia muito de navegador. para o navegador. O Firefox é extremamente rápido em algumas das funções, e em alguns domina o Chrome. (Eu imagino que haveria alguns cenários onde o IE dominaria também). Acredito que é melhor preferir um código cujo desempenho seja mais consistente entre os navegadores.

    Leia a postagem do blog anterior e, em vez de acreditar no assunto, julgue por si mesmo executando os benchmarks . Estou atordoado agora, vendo uma lodash se apresentando 100-150% mais rápida do que o sublinhado em funções nativas simples , como o Array.every no Chrome!

  2. Os extras em lodash também são bastante úteis.

  3. Quanto ao comentário altamente falado de Xananax sugerindo contribuição para o código de sublinhado: é sempre melhor ter boa concorrência, não apenas manter a inovação funcionando, mas também levar você a se manter (ou a sua biblioteca) em boa forma.

Aqui está uma lista de diferenças entre o lodash, e o underscore-build é um substituto para os seus projetos de sublinhado.

Se, como eu, você estava esperando uma lista de diferenças de uso entre sublinhado e lodash, há um guia para migrar de sublinhado para lodash .

Aqui está o estado atual para a posteridade:

  • Sublinhado _.compose é Lodash _.flowRight
  • Sublinhado _.contains é Lodash _.includes
  • Sublinhado _.findWhere é Lodash _.find
  • Sublinhado _.invoke é Lodash _.invokeMap
  • Underscore _.mapObject is Lodash _.mapValues
  • Sublinhado _.pluck é Lodash _.map
  • Sublinhado _.where é Lodash _.filter
  • Sublinhado _.any é Lodash _.some
  • Sublinhado _.all é Lodash _.every
  • Sublinhado _.each não permite sair retornando false
  • O sublinhado _.flatten é profundo por padrão, enquanto Lodash é superficial
  • Underscore _.isFinite não se alinha com Number.isFinite
    (eg _.isFinite('1') retorna true em Underscore mas false em Lodash)
  • Sublinhado _.matches taquigrafia não suporta comparações profundas
    (por exemplo, _.filter(objects, { 'a': { 'b': 'c' } }) )
  • Underscore ≥ 1.7 & Lodash mudaram sua syntax _.template para
    _.template(string, option)(data)
  • Lodash _.uniq não aceita uma function iteratee como Underscore. Use Lodash _.uniqBy
  • Lodash _.first e ._last não aceitam um argumento n como Underscore. Use slice
  • Lodash _.memoize caches são objects semelhantes a Map
  • Lodash suporta encadeamento implícito , encadeamento ocioso e fusão de atalhos
  • Lodash dividiu o sobrecarregado _.head , _.last , _.rest , & _.initial out em
    _.take , _.takeRight , _.drop , & _.dropRight
    (ie _.head(array, 2) em Underscore é _.take(array, 2) em Lodash)

Isso é 2014 e um par de anos atrasado. Ainda acho que meu ponto é válido:

IMHO esta discussão ficou fora de proporção um pouco. Citando a postagem do blog acima mencionada:

A maioria das bibliotecas de utilitários JavaScript, como Underscore, Valentine e wu, se baseiam na “abordagem dual nativa”. Essa abordagem prefere implementações nativas, voltando a usar JavaScript apenas se o equivalente nativo não for suportado. Mas jsPerf revelou uma tendência interessante: a maneira mais eficiente de fazer iterações em uma matriz ou em uma coleção de array é evitar as implementações nativas por completo, optando por loops simples.

Como se “simples loops” e “vanilla Javascript” fossem mais nativos do que implementações de methods Array ou Object. Caramba …

Certamente seria bom ter uma única fonte de verdade, mas não há. Mesmo que você tenha dito o contrário, não há Deus Baunilha, minha querida. Eu sinto Muito. A única suposição que realmente é válida é que todos nós estamos escrevendo código Javascript que tem um bom desempenho em todos os principais navegadores, sabendo que todos eles têm diferentes implementações das mesmas coisas. É uma puta para lidar, para dizer o mínimo. Mas essa é a premissa, quer você goste ou não.

Talvez vocês estejam trabalhando em projetos de larga escala que precisam de desempenho chocante para que você realmente veja a diferença entre 850.000 (sublinhado) e 2.500.000 (lodash) iterações em uma lista por segundo no momento!

Eu por um não sou. Quer dizer, eu trabalhei em projetos onde tive que lidar com problemas de performance, mas eles nunca foram resolvidos ou causados ​​por Underscore nem Lo-Dash. E a menos que eu consiga as diferenças reais em implementação e performance (estamos falando agora do C ++) de vamos dizer um loop sobre um iterável (object ou array, esparso ou não!), Eu prefiro não ser incomodado com qualquer reivindicações baseadas nos resultados de uma plataforma de referência que já é opinativa .

Só precisa de uma única atualização, digamos, da Rhino para incendiar suas implementações de methods de Array de uma forma que nem um único padre de “methods de loop medievais executam melhor e para sempre e tudo mais” pode argumentar sobre o simples fato de que todos Um súbito método de arranjo em FF é muito mais rápido do que seu criticado brainfuck. Cara, você simplesmente não pode enganar seu ambiente de execução enganando seu ambiente de tempo de execução! Pense nisso quando promover …

seu cinto de utilidades

… próxima vez.

Então, para mantê-lo relevante:

  • Use Underscore se você estiver em praticidade sem sacrificar o ish nativo.
  • Use o Lo-Dash se você estiver em praticidade e como seu catálogo de resources estendidos (cópia profunda etc.) e se você estiver em necessidade desesperada de desempenho instantâneo e, o mais importante, não se importe em escolher uma alternativa assim que a API nativa for workaurounds opinativos. O que vai acontecer em breve. Período.
  • Existe até uma terceira solução. FAÇA VOCÊ MESMO! Conheça seus ambientes. Conheça as inconsistências. Leia o código deles (de John-David e Jeremy ). Não use isso ou aquilo sem poder explicar por que uma camada de consistência / compatibilidade é realmente necessária e aprimora seu stream de trabalho ou melhora o desempenho do seu aplicativo. É muito provável que seus requisitos estejam satisfeitos com um simples polyfill que você é perfeitamente capaz de escrever sozinho. Ambas as bibliotecas são simplesmente baunilha com um pouco de açúcar. Ambos brigam por quem está servindo a mais doce torta . Mas acredite em mim, no final ambos estão apenas cozinhando com água. Não há Deus Baunilha, então não pode haver papa Baunilha, certo?

Escolha qualquer abordagem que melhor atenda às suas necessidades. Como sempre. Eu prefiro fallbacks em implementações reais sobre cheats runtime opinativos a qualquer momento, mas mesmo isso parece ser uma questão de gosto nos dias de hoje. Atenha-se aos resources de qualidade como http://developer.mozilla.com e http://caniuse.com e você ficará bem.

Eu concordo com a maioria das coisas ditas aqui, mas eu só quero apontar um argumento em favor do underscore.js: o tamanho da biblioteca.

Especialmente no caso de você estar desenvolvendo um aplicativo ou site que pretenda ser usado principalmente em dispositivos móveis, o tamanho do pacote resultante e o efeito no tempo de boot ou download podem ter um papel importante.

Para comparação, esses tamanhos são aqueles que eu notei com o explorador de mapas de origem depois de executar o serviço iônico:

 lodash: 523kB underscore.js: 51.6kb 

Não tenho certeza se foi isso que o OP quis dizer, mas cheguei a essa pergunta porque estava procurando uma lista de problemas que eu tenho que ter em mente ao migrar do sublinhado para o lodash.

Eu realmente aprecio se alguém postou um artigo com uma lista completa de tais diferenças. Deixe-me começar com as coisas que aprendi da maneira mais difícil (isto é, coisas que fizeram meu código explodir na produção: /):

  • _.flatten em sublinhado é profundo por padrão e você tem que passar verdadeiro como segundo argumento para torná-lo superficial. Em lodash, é superficial por padrão e passar true como segundo argumento irá torná-lo profundo! 🙂
  • _.last no sublinhado aceita um segundo argumento que informa quantos elementos você deseja. Em lodash não existe essa opção. Você pode emular isso com .slice
  • _.first (mesmo problema)
  • _.template no sublinhado pode ser usado de várias maneiras, uma das quais é fornecer a string e os dados do modelo e recuperar o HTML (ou pelo menos é assim que funcionou há algum tempo). No lodash você recebe uma function que deve ser alimentada com os dados.
  • _(something).map(foo) funciona no sublinhado, mas no lodash eu tive que reescrevê-lo para _.map(something,foo) . Talvez isso fosse apenas uma TypeScript TypeScript

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

Último artigo comparando os dois por Ben McCormick:

  1. A API do Lo-Dash é um superconjunto do Underscore.

  2. Sob o capô [Lo-Dash] foi completamente reescrito.

  3. Lo-Dash definitivamente não é mais lento que Underscore.

  4. O que o Lo-Dash adicionou?

    • Melhorias de usabilidade
    • Funcionalidade Extra
    • Ganhos de desempenho
    • Sintaxes de taquigrafia para encadeamento
    • Custom Builds para usar apenas o que você precisa
    • Versão semântica e cobertura de código de 100%

Acabei de encontrar uma diferença que acabou sendo importante para mim. A versão não compatível com o sublinhado de _.extend() do _.extend() não copia propriedades ou methods definidos por nível de class.

Eu criei um teste do Jasmine no CoffeeScript que demonstra isso:

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

Felizmente, o lodash.underscore.js preserva o comportamento do Underscore de copiar tudo, o que, para minha situação, era o comportamento desejado.

O lodash tem o _.mapValues() que é idêntico ao _.mapObject() do _.mapObject() .

Na maior parte, o sublinhado é um subconjunto do lodash. Às vezes, como o sublinhado atual terá funções pequenas legais, o lodash não tem como mapObject. Este me poupou muito tempo no desenvolvimento do meu projeto.