2011-07-01 12 views
5

Może ktoś wyjaśnić mi jedno:ciąg JavaScript prędkość konkatenacji

http://jsperf.com/string-concatenation-1/2

Jeśli jesteś leniwy, testowałem A) vs b):

A)

var innerHTML = ""; 

items.forEach(function(item) { 
    innerHTML += item; 
}); 

B)

var innerHTML = items.join(""); 

Gdzie items dla obu testów jest tą samą tablicą składającą się z 500 elementów, przy czym każdy ciąg jest losowy i ma długość od 100 do 400 znaków.

A) kończy się o 10 razy szybciej. Jak to możliwe - zawsze uważałem, że łączenie się przy użyciu join("") było sztuczką optymalizacyjną. Czy moje testy są błędne?

+0

Jeśli nie dołączasz do bardzo dużej liczby ciągów (bardzo duże jest zależne od przeglądarki), 'Array.Join' jest wolniejsze niż' + ' – Mrchief

Odpowiedz

8

Używanie join("") było sztuczką optymalizacyjną do tworzenia dużych ciągów znaków w IE6 w celu uniknięcia kopii bufora w postaci O(n**2). Nigdy nie oczekiwano, że będzie to ogromna wygrana w osiągnięciu kompilacji małych ciągów znaków, ponieważ tylko O(n**2) naprawdę dominuje nad obciążeniem tablicy dla dużego n.

Współcześni tłumacze omijają to, używając "ciągów zależnych". Zobacz to mozilla bug, aby uzyskać wyjaśnienie zależnych łańcuchów oraz niektóre zalety i wady.

Zasadniczo, nowoczesne tłumaczy wie o wielu różnych rodzajów strun:

  1. Tablica znaków
  2. Plasterek (podciąg) z innym ciągiem
  3. będąca połączeniem dwóch innych ciągów

To powoduje, że konkatenacja i podciąg O (1) kosztem niekiedy utrzymywania zbyt dużej ilości substratu bufora, powodującego nieefektywność lub złożoność w garbie e kolekcjoner.

Niektórzy współcześni interpretatorzy odegrali ideę dalszego rozkładu (1) w bajcie [] s dla ciągów tylko ASCII i tablic uint16, gdy ciąg zawiera jednostkę kodową UTF-16, która nie mieści się w jednym bajt. Ale nie wiem, czy ten pomysł rzeczywiście istnieje w jakimkolwiek tłumaczu.