Najbardziej efektywny sposób łączenia ciągów w JavaScript?

163

W JavaScript mam pętlę, która ma wiele iteracji, aw każdej iteracji tworzę ogromny ciąg z wieloma +=operatorami. Czy istnieje wydajniejszy sposób tworzenia łańcucha? Myślałem o stworzeniu dynamicznej tablicy, w której będę dodawać do niej ciągi, a następnie wykonywać łączenie. Czy ktoś może wyjaśnić i podać przykład najszybszego sposobu, aby to zrobić?

omega
źródło
2
Do czego używasz sznurka? Wszelkie wskazówki dotyczące wydajności będą się różnić w zależności od środowiska, rozmiarów łańcuchów, sposobu, w jaki określony silnik js optymalizuje różne operacje, itp.
Ben McCormick
1
może być duplikatem stackoverflow.com/questions/7299010/…
rab
5
Sprawdź ten link jsperf.com/join-concat/2
rab
Używam IE9, ale jest w trybie zgodności IE8 (którego nie mogę zmienić). Ogromny ciąg to coś, co wstawię do DOM za pomocą jquery.
omega
Zobacz także konkatenację ciągów JavaScript
Bergi,

Odpowiedzi:

135

Wydaje się, że bazuje na testach porównawczych JSPerf , według których używanie +=jest najszybszą metodą, choć niekoniecznie w każdej przeglądarce.

Wydaje się , że do budowania łańcuchów w DOM, lepiej jest najpierw połączyć łańcuch, a następnie dodać go do DOM, zamiast dodawać go iteracyjnie do DOM. Powinieneś jednak porównać swój własny przypadek.

(Dzięki @zAlbee za korektę)

Jakub Hampl
źródło
1
Zajrzyj na linkowaną stronę. Wydaje się, że istnieje niewielka różnica między +=wykonywaniem złączenia a łączeniem na tablicy.
Jakub Hampl
Wydaje się, że dodanie go do DOM dla każdego ciągu jest 66%(dla IE9) szybsze niż utworzenie łańcucha, a następnie dodanie ciągu do DOM.
omega
strona, do której prowadzi link, używa + = w obu testach, nie widać .join (), więc jest to bezsensowny test, który pokazuje tylko szum jako każdą „różnicę”. dobry przykład tego, jak głośny może być js ... dom jest wolniejszy niż string, więc używaj go oszczędnie.
dandavis
Czas to tylko jeden składnik. Zastanawiam się, jaki wpływ na GC mają różne metody w przypadku procedur iteracyjnych?
David Bradley
Dla dużych ciągów Array.join może być korzystne ze względu na ciąg concat bardzo nieprzyjemny błąd pamięci bugs.chromium.org/p/v8/issues/detail?id=3175
mwag
70

Nie mam komentarza do samej konkatenacji, ale chciałbym zaznaczyć, że sugestia @Jakub Hampl:

Do budowania łańcuchów w DOM, w niektórych przypadkach lepiej byłoby iteracyjnie dodawać do DOM, zamiast dodawać od razu ogromny ciąg.

jest błędne, ponieważ opiera się na błędnym teście. Ten test w rzeczywistości nigdy nie dołącza do DOM.

Ten naprawiony test pokazuje, że utworzenie całego ciągu na raz przed jego renderowaniem jest dużo, DUŻO szybsze. To nawet nie jest konkurs.

(Przepraszam, że to osobna odpowiedź, ale nie mam jeszcze wystarczającej liczby przedstawicieli, aby komentować odpowiedzi).

zAlbee
źródło
4
Myślę, że warto być odpowiedzią samą w sobie, ponieważ zawiera test i wniosek (chociaż test jest oparty / inspirowany inną odpowiedzią, to powinno być ok), nie ma potrzeby przepraszać.
user202729
14

Trzy lata minęły od odpowiedzi na to pytanie, ale i tak udzielę odpowiedzi :)

W rzeczywistości przyjęta odpowiedź nie jest w pełni poprawna. Test Jakuba wykorzystuje zakodowany ciąg znaków, który pozwala silnikowi JS na optymalizację wykonywania kodu (V8 Google jest w tym naprawdę dobry!). Ale gdy tylko użyjesz całkowicie losowych ciągów ( tutaj jest JSPerf ), konkatenacja ciągów będzie na drugim miejscu.

Volodymyr Usarskyy
źródło
Co ciekawe, w przypadku Chrome 54 i Firefox 45 na moim komputerze z systemem Windows concat jest ponad dwa razy szybszy niż pozostałe dwa przy użyciu Twojej wersji. IE 11 ma wszystkie trzy tak wolno, jak non-concat w pozostałych dwóch przeglądarkach.
ShawnFumo
4
Różni się od wersji do wersji. Myślę, że w tej chwili maszyna wirtualna Chrome może zawierać pewną wstępną optymalizację dla tego przypadku. Testowałem ponownie na Chrome v53 i konkatenacja jest teraz najszybszym rozwiązaniem: D Ten sam sprzęt, ale inna wersja Chrome daje zupełnie inne wyniki.
Volodymyr Usarskyy
8

Możesz również wykonać konkatację ciągów z literałami szablonu . Zaktualizowałem testy JSPerf innych plakatów, aby je uwzględnić.

for (var res = '', i = 0; i < data.length; i++) {
  res = `${res}${data[i]}`;
}
Madbreaks
źródło