Czy javascript używa ciągów niezmiennych lub modyfikowalnych? Czy potrzebuję „kreatora ciągów”?
javascript
string
DevelopisChris
źródło
źródło
Odpowiedzi:
Są niezmienne. Nie możesz zmienić znaku w ciągu za pomocą czegoś takiego
var myString = "abbdef"; myString[2] = 'c'
. Metody manipulacji ciągami, takie jaktrim
,slice
zwracają nowe ciągi.W ten sam sposób, jeśli masz dwa odwołania do tego samego ciągu, modyfikowanie jednego nie wpływa na drugie
Jednak zawsze słyszałem, co Ash wspomniał w swojej odpowiedzi (że użycie Array.join jest szybsze do konkatenacji), więc chciałem przetestować różne metody konkatenacji ciągów i wyodrębnienia najszybszej drogi do StringBuilder. Napisałem kilka testów, aby sprawdzić, czy to prawda (nie jest!).
Uznałem, że to najszybszy sposób, choć ciągle myślałem, że dodanie wywołania metody może spowolnić ...
Oto testy prędkości działania. Wszyscy trzej tworzą gigantyczną strunę złożoną ze
"Hello diggity dog"
stu tysięcy połączeń w pustą strunę.Stworzyłem trzy typy testów
Array.push
iArray.join
Array.push
, a następnie używanieArray.join
Potem stworzył te same trzy testy przez abstrahując je
StringBuilderConcat
,StringBuilderArrayPush
aStringBuilderArrayIndex
http://jsperf.com/string-concat-without-sringbuilder/5 Proszę tam pojechać i testy zakończą więc możemy uzyskać próbkę piękny. Zauważ, że naprawiłem mały błąd, więc dane do testów zostały wyczyszczone, zaktualizuję tabelę, gdy będzie wystarczająca ilość danych o wydajności. Przejdź do http://jsperf.com/string-concat-without-sringbuilder/5, aby uzyskać starą tabelę danych.Oto kilka liczb (najnowsza aktualizacja Ma5rch 2018), jeśli nie chcesz korzystać z linku. Liczba na każdym teście to 1000 operacji na sekundę (im wyższa, tym lepiej )
Wyniki
Obecnie wszystkie wiecznie zielone przeglądarki dobrze radzą sobie z konkatenacją ciągów.
Array.join
pomaga tylko IE 11Ogólnie Opera jest najszybsza, 4 razy szybsza niż Array.join
Firefox jest drugi i
Array.join
jest tylko nieco wolniejszy w FF, ale znacznie wolniejszy (3x) w Chrome.Chrome jest trzeci, ale konkat ciąg jest 3 razy szybszy niż Array.join
Tworzenie StringBuilder wydaje się nie wpływać zbytnio na wydajność.
Mam nadzieję, że ktoś inny uzna to za przydatne
Inny przypadek testowy
Ponieważ @RoyTinker myślał, że mój test jest wadliwy, stworzyłem nowy przypadek, który nie tworzy dużego łańcucha przez połączenie tego samego łańcucha, używa innego znaku dla każdej iteracji. Łączenie strun wciąż wydawało się szybsze lub równie szybkie. Uruchommy te testy.
Sugeruję, aby każdy zastanowił się nad innymi sposobami przetestowania tego i dodaj nowe linki do różnych przypadków testowych poniżej.
http://jsperf.com/string-concat-without-sringbuilder/7
źródło
join
konkatenacji ciągów vs, a tym samym zbudowanie tablicy przed testem. Nie sądzę, że to oszustwo, jeśli ten cel jest zrozumiany (ijoin
wylicza tablicę wewnętrznie, więc nie jest też oszustwem pominięciefor
pętli wjoin
teście).Array.join
z książki o nosorożcach :
źródło
null
undefined
number
iboolean
. Ciągi są przypisywane przez wartość, a nie przez odniesienie i są przekazywane jako takie. Zatem ciągi znaków są nie tylko niezmienne, są wartością . Zmiana ciąg"hello"
być"world"
jakby uznając, że od teraz numer 3 to numer 4 ... to nie ma sensu.var a = "hello";var b=a;a.x=5;console.log(a.x,b.x);
String
obiekty utworzone za pomocą konstruktora ciągów są owijane wokół wartości ciągu JavaScript. Dostęp do wartości ciągu typu pudełkowego można uzyskać za pomocą.valueOf()
funkcji - dotyczy to równieżNumber
obiektów i wartości liczbowych. Ważne jest, aby pamiętać, żeString
obiekty utworzone przy użyciunew String
nie są rzeczywistymi ciągami, ale są owijkami lub ramkami wokół ciągów. Zobacz es5.github.io/#x15.5.2.1 . O tym, jak rzeczy przekształcają się w obiekty, zobacz es5.github.io/#x9.9Wskazówka dotycząca wydajności:
Jeśli musisz połączyć duże łańcuchy, umieść części łańcucha w tablicy i użyj
Array.Join()
metody, aby uzyskać cały łańcuch. Może to być wielokrotnie szybsze w przypadku łączenia dużej liczby ciągów.W
StringBuilder
JavaScript nie ma .źródło
Aby wyjaśnić proste umysły, takie jak moje (z MDN ):
Niezmienny oznacza, że:
Wygląda na to, że mutujemy ciąg „immutableString”, ale tak nie jest. Zamiast:
źródło
Wartość typu ciągu jest niezmienna, ale obiekt String, który jest tworzony za pomocą konstruktora String (), jest zmienny, ponieważ jest to obiekt i można do niego dodawać nowe właściwości.
Tymczasem, chociaż możesz dodawać nowe właściwości, nie możesz zmieniać już istniejących właściwości
Zrzut ekranu z testu w konsoli Chrome
Podsumowując: 1. cała wartość typu łańcucha (typ pierwotny) jest niezmienna. 2. Obiekt String jest zmienny, ale zawarta w nim wartość typu łańcucha (typ pierwotny) jest niezmienna.
źródło
new String
generuje zmienne opakowanie wokół niezmiennego ciąguString
obiektu (opakowania), co oznacza, że nie jest on niezmienny (domyślnie; jak każdy inny obiekt, do którego można go wywołaćObject.freeze
, aby stał się niezmienny). Ale prymitywny typ wartości ciągu, niezależnie od tego, czy jest zawarty wString
opakowaniu obiektu, czy nie, jest zawsze niezmienny.Ciągi są niezmienne - nie mogą się zmieniać, możemy tylko tworzyć nowe.
Przykład:
źródło
Jeśli chodzi o twoje pytanie (w komentarzu do odpowiedzi Asha) dotyczące StringBuilder w ASP.NET Ajax, eksperci wydają się nie zgadzać w tej kwestii.
Christian Wenz mówi w swojej książce Programowanie ASP.NET AJAX (O'Reilly), że „to podejście nie ma żadnego mierzalnego wpływu na pamięć (w rzeczywistości implementacja wydaje się być wolniejsza niż standardowe”).
Z drugiej strony Gallo i wsp. W swojej książce ASP.NET AJAX in Action (Manning) stwierdzili, że „gdy liczba ciągów do konkatenacji jest większa, konstruktor ciągów staje się niezbędnym obiektem, aby uniknąć ogromnego spadku wydajności”.
Sądzę, że musisz przeprowadzić własne testy porównawcze, a wyniki mogą się różnić w różnych przeglądarkach. Jednak nawet jeśli nie poprawi to wydajności, nadal może być uważane za „przydatne” dla programistów przyzwyczajonych do kodowania za pomocą StringBuilders w językach takich jak C # lub Java.
źródło
To późny post, ale wśród odpowiedzi nie znalazłem dobrego cytatu z książki.
Oto określony, z wyjątkiem wiarygodnej książki:
Odpowiedź, która cytuje fragment książki Rhino, słusznie dotyczy niezmienności łańcucha, ale błędnie mówi: „Łańcuchy są przypisywane przez odniesienie, a nie przez wartość”. (prawdopodobnie pierwotnie zamierzali umieścić słowa w odwrotny sposób).
Błędne przekonanie o „referencji / wartości” wyjaśniono w rozdziale „Profesjonalny JavaScript” w rozdziale „Podstawowe i referencyjne wartości”:
w przeciwieństwie do obiektów :
źródło
Ciągi JavaScript są rzeczywiście niezmienne.
źródło
Ciągi w JavaScript są niezmienne
źródło