é o operador + com menos desempenho do que StringBuffer.append ()


91

Na minha equipe, geralmente fazemos concatentação de strings como esta:

var url = // some dynamically generated URL
var sb = new StringBuffer();
sb.append("<a href='").append(url).append("'>click here</a>");

Obviamente, o seguinte é muito mais legível:

var url = // some dynamically generated URL
var sb = "<a href='" + url + "'>click here</a>";

Mas os especialistas em JS afirmam que o +operador tem menos desempenho do que StringBuffer.append(). Isso é verdade mesmo?


92
Não há StringBuffer em javascript
Tomas

7
Don, você estava se referindo a Java?
James McMahon

Minha experiência [].join('')mostrou um comportamento realmente conectado, então voltei para +: - /
martyglaubitz

1
Eu sei que a questão fundamental aqui é sobre a concatenação de strings, mas você deve ter cuidado ao criar elementos html como este. Seu exemplo pode falhar se urlcontiver 'ou \n.
elegante

Respostas:


46

O Internet Explorer é o único navegador que realmente sofre com isso no mundo de hoje. (As versões 5, 6 e 7 eram lentas como cães. 8 não mostra a mesma degradação.) Além disso, o IE fica cada vez mais lento quanto mais longa a corda.

Se você tiver strings longas para concatenar, use definitivamente uma técnica array.join. (Ou algum wrapper StringBuffer em torno disso, para facilitar a leitura.) Mas se suas strings forem curtas, não se preocupe.


102

Seu exemplo não é bom porque é muito improvável que o desempenho seja significativamente diferente. Em seu exemplo, a legibilidade deve superar o desempenho porque o ganho de desempenho de um em relação ao outro é insignificante. Os benefícios de uma matriz (StringBuffer) são aparentes apenas quando você está fazendo muitas concatentações. Mesmo assim, sua milhagem pode variar dependendo do seu navegador.

Aqui está uma análise de desempenho detalhada que mostra o desempenho usando todos os diferentes métodos de concatenação JavaScript em muitos navegadores diferentes; Desempenho e análise da coluna

join () uma vez, concat () uma vez, join () para, + = para, concat () para

Mais:
Ajaxian >> Desempenho de String no IE: Array.join vs + = continuado


9
Em relação ao gráfico, caso não seja óbvio; menor é melhor.
Teekin de

1
"Em primeiro lugar, com as melhorias de desempenho com o IE7, não precisamos mais considerar o uso de um caminho alternativo ao fazer operações de string em grande escala; usar Array.join em uma situação iterativa não oferece grandes vantagens do que usar + = na mesma situação. Além disso, as diferenças com o IE6 eram pequenas o suficiente para permitir que você não se incomodasse com a bifurcação para aquela versão específica. "
Chris S

2
@Chris, isso não é verdade. Compare esses dois violinos no IE7 : jsfiddle.net/9uS4n/5 (rápido) vs. jsfiddle.net/9uS4n/2 (lento). Parece haver uma melhoria de pelo menos 1000 vezes no desempenho usando a join()técnica.
Kirk Woll

Bela explicação. Leia também: iliadraznin.com/2012/03/…
will824

37

Sim, é verdade, mas você não deve se importar. Escolha aquele que é mais fácil de ler. Se você tiver que avaliar seu aplicativo, concentre-se nos gargalos.

Eu imagino que a concatenação de strings não será o seu gargalo.


31

Acordado com Michael Haren .

Considere também o uso de arrays e join se o desempenho for realmente um problema.

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));

3
Eu sei que uma resposta correta foi selecionada, mas esta resposta tem um exemplo mais útil.
Jason Sperske,

1
Wow apenas wow. Compare esses dois violinos no IE7 : jsfiddle.net/9uS4n/5 (rápido) vs. jsfiddle.net/9uS4n/2 (lento). Parece haver uma melhoria de pelo menos 1000 vezes no desempenho usando esta técnica.
Kirk Woll

@KirkWoll: Pode ser que você queira usar jsPerf no futuro para que possamos comparar facilmente os resultados.
rvighne de

também tenho feito isso recentemente, estilo de código semelhante a um .NET StringBuilder, var sb = []; sb.push ("seção 1"); sb.push ("seção 2"); return sb.join ('');
Sam Jones


18

Experimente isto:

var s = ["<a href='", url, "'>click here</a>"].join("");

Bem, a postagem que você vinculou em sua resposta tenta refutar especificamente o "mito" de Array.join que minha resposta sugere. Então, talvez não. Apenas postei o que vi ser mais rápido na prática.
Rahul

amo este método de concat de string.
bkwdesign

8

Como já alguns usuários notaram: Isso é irrelevante para strings pequenas.

E novos mecanismos de JavaScript no Firefox, Safari ou Google Chrome otimizam para

"<a href='" + url + "'>click here</a>";

é tão rápido quanto

["<a href='", url, "'>click here</a>"].join("");

8

JavaScript não tem um objeto StringBuffer nativo, então presumo que seja de uma biblioteca que você está usando ou de um recurso de um ambiente host incomum (ou seja, não é um navegador).

Duvido que uma biblioteca (escrita em JS) produza algo mais rápido, embora um objeto StringBuffer nativo possa. A resposta definitiva pode ser encontrada com um criador de perfil (se você estiver executando em um navegador, o Firebug fornecerá um criador de perfil para o mecanismo JS encontrado no Firefox).


6

Nas palavras de Knuth, "a otimização prematura é a raiz de todo o mal!" A pequena diferença de qualquer maneira provavelmente não terá muito efeito no final; Eu escolheria o mais legível.


1
Tradicionalmente, StringBuffer é usado sobre concatenação porque o primeiro tem complexidade de tempo O (N), enquanto o último é O (N ^ 2), portanto, a diferença é significativa para N grande (mas não para N pequeno). Em qualquer caso, o cenário O (N ^ 2) pode não ser o caso em JavaScript, dependendo do ambiente em uso.
redcalx

4

O método mais fácil de ler economiza aos humanos quantidades perceptíveis de tempo ao olhar o código, enquanto o método "mais rápido" desperdiça apenas quantidades de tempo imperceptíveis e provavelmente insignificantes quando as pessoas estão navegando na página.

Eu sei que esta postagem é idiota, mas acidentalmente postei algo totalmente diferente pensando que este era um tópico diferente e não sei como deletar postagens. Foi mal...


3

É muito fácil configurar um benchmark rápido e verificar as variações de desempenho do Javascript usando jspref.com . Que provavelmente não estava por perto quando esta pergunta foi feita. Mas para as pessoas que estão tropeçando nessa questão, devem dar uma olhada no site.

Fiz um teste rápido de vários métodos de concatenação em http://jsperf.com/string-concat-methods-test .


A julgar por isso, parece que hoje em dia a concatenação com o operador + é definitivamente o caminho a seguir. A menos que eu esteja lendo errado. O que é totalmente plausível.
Richard

2

Gosto de usar um estilo funcional, como:

function href(url,txt) {
  return "<a href='" +url+ "'>" +txt+ "</a>"
}

function li(txt) {
  return "<li>" +txt+ "</li>"
}

function ul(arr) {
  return "<ul>" + arr.map(li).join("") + "</ul>"
}

document.write(
  ul(
    [
      href("http://url1","link1"),
      href("http://url2","link2"),
      href("http://url3","link3")
    ]
  )
)

Este estilo parece legível e transparente. Isso leva à criação de utilitários que reduzem a repetição no código.

Isso também tende a usar strings intermediárias automaticamente.


1

Até onde eu sei, cada concatenação implica uma realocação de memória. Então o problema não é o operador utilizado para fazer isso, a solução é reduzir o número de concatenações. Por exemplo, faça as concatenações fora das estruturas de iteração quando puder.


Este não é realmente um conselho ruim, não sei por que foi rejeitado tanto. Sei que não responde à pergunta específica, mas merece reconhecimento por ser geralmente um bom conselho.
ausência de pálpebras

0

Sim, de acordo com os benchmarks usuais. EX .: http://mckoss.com/jscript/SpeedTrial.htm .

Mas para as cordas pequenas, isso é irrelevante. Você só se preocupará com apresentações em cordas muito grandes. Além do mais, na maioria dos scripts JS, o gargalo raramente está nas manipulações das cordas, uma vez que não há o suficiente.

É melhor você observar a manipulação do DOM.


O link está morto .. https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm aponta para a versão do arquivo da web.
Tony
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.