Verwendet Javascript unveränderliche oder veränderbare Zeichenfolgen? Benötige ich einen "String Builder"?
javascript
string
Entwicklung von Chris
quelle
quelle
Antworten:
Sie sind unveränderlich. Sie können ein Zeichen innerhalb einer Zeichenfolge nicht mit so etwas wie ändern
var myString = "abbdef"; myString[2] = 'c'
. Die String - Manipulationsmethoden wietrim
,slice
zurückkehren neue Saiten.Wenn Sie zwei Verweise auf dieselbe Zeichenfolge haben, wirkt sich das Ändern einer auf die andere nicht aus
Ich habe jedoch immer gehört, was Ash in seiner Antwort erwähnt hat (dass die Verwendung von Array.join für die Verkettung schneller ist), daher wollte ich die verschiedenen Methoden zum Verketten von Zeichenfolgen und zum Abstrahieren des schnellsten Wegs in einen StringBuilder testen. Ich habe einige Tests geschrieben, um zu sehen, ob dies wahr ist (ist es nicht!).
Dies war meiner Meinung nach der schnellste Weg, obwohl ich immer wieder dachte, dass das Hinzufügen eines Methodenaufrufs ihn langsamer machen könnte ...
Hier sind Leistungsgeschwindigkeitstests. Alle drei bilden eine gigantische Zeichenfolge, die aus der
"Hello diggity dog"
hunderttausendfachen Verkettung zu einer leeren Zeichenfolge besteht.Ich habe drei Arten von Tests erstellt
Array.push
undArray.join
Array.push
, und Verwenden vonArray.join
Dann habe ich die gleichen drei Tests , die von ihnen in abstrahiert
StringBuilderConcat
,StringBuilderArrayPush
undStringBuilderArrayIndex
http://jsperf.com/string-concat-without-sringbuilder/5 Bitte gehen Sie dort und laufen Tests , so dass wir eine schöne Probe erhalten. Beachten Sie, dass ich einen kleinen Fehler behoben habe, sodass die Daten für die Tests gelöscht wurden. Ich werde die Tabelle aktualisieren, sobald genügend Leistungsdaten vorhanden sind. Gehen Sie zu http://jsperf.com/string-concat-without-sringbuilder/5Die alte Datentabelle finden .Hier sind einige Zahlen (letztes Update in Ma5rch 2018), wenn Sie dem Link nicht folgen möchten. Die Zahl bei jedem Test ist in 1000 Operationen / Sekunde ( höher ist besser )
Ergebnisse
Heutzutage handhaben alle immergrünen Browser die Verkettung von Zeichenfolgen gut.
Array.join
hilft nur IE 11Insgesamt ist Opera am schnellsten, viermal so schnell wie Array.join
Firefox ist an zweiter Stelle und
Array.join
in FF nur geringfügig langsamer, in Chrome jedoch erheblich langsamer (3x).Chrome ist an dritter Stelle, aber String Concat ist dreimal schneller als Array.join
Das Erstellen eines StringBuilder scheint die Leistung nicht zu stark zu beeinträchtigen.
Hoffe, jemand anderes findet das nützlich
Unterschiedlicher Testfall
Da @RoyTinker meinte, mein Test sei fehlerhaft, habe ich einen neuen Fall erstellt, bei dem keine große Zeichenfolge durch Verketten derselben Zeichenfolge erstellt wird. Für jede Iteration wird ein anderes Zeichen verwendet. Die Verkettung von Zeichenfolgen schien immer noch schneller oder genauso schnell zu sein. Lassen Sie uns diese Tests zum Laufen bringen.
Ich schlage vor, dass jeder über andere Möglichkeiten nachdenken sollte, um dies zu testen, und neue Links zu verschiedenen Testfällen hinzufügen kann.
http://jsperf.com/string-concat-without-sringbuilder/7
quelle
join
Verkettung und String-Verkettung zu beschränken und so das Array vor dem Test zu erstellen . Ich denke nicht, dass das Betrug ist, wenn dieses Ziel verstanden wird (undjoin
das Array intern auflistet, so dass es auch kein Betrug ist, einefor
Schleife aus demjoin
Test wegzulassen ).Array.join
aus dem Nashornbuch :
quelle
null
undefined
number
und einer der wenigen 5 Werttypenboolean
. Zeichenfolgen werden nach Wert und nicht nach Referenz zugewiesen und als solche übergeben. Strings sind also nicht nur unveränderlich, sie sind ein Wert . Die Zeichenfolge ändern"hello"
zu sein"world"
ist wie die von nun an die Nummer 3 der Entscheidung ist die Nummer 4 ... es macht keinen Sinn.var a = "hello";var b=a;a.x=5;console.log(a.x,b.x);
String
mit dem Zeichenfolgenkonstruktor erstellte Objekte sind Wrapper um JavaScript-Zeichenfolgenwerte. Mit der.valueOf()
Funktion können Sie auf den Zeichenfolgenwert des Box-Typs zugreifen. Dies gilt auch fürNumber
Objekte und Zahlenwerte. Es ist wichtig zu beachten, dassString
Objekte, die mit erstellt wurden,new String
keine tatsächlichen Zeichenfolgen sind, sondern Wrapper oder Kästchen um Zeichenfolgen. Siehe es5.github.io/#x15.5.2.1 . InformationenLeistungstipp:
Wenn Sie große Zeichenfolgen verketten müssen, fügen Sie die Zeichenfolgenteile in ein Array ein und verwenden Sie die
Array.Join()
Methode, um die Gesamtzeichenfolge abzurufen. Dies kann für die Verkettung einer großen Anzahl von Zeichenfolgen um ein Vielfaches schneller sein.StringBuilder
In JavaScript gibt es keine .quelle
Nur um für einfache Köpfe wie meine (von MDN ) zu klären :
Unveränderlich bedeutet:
Es sieht so aus, als würden wir den String 'immutableString' mutieren, aber das sind wir nicht. Stattdessen:
quelle
Der Wert für den Zeichenfolgentyp ist unveränderlich, aber das Zeichenfolgenobjekt , das mit dem Konstruktor String () erstellt wird, kann geändert werden, da es sich um ein Objekt handelt und Sie ihm neue Eigenschaften hinzufügen können.
Obwohl Sie neue Eigenschaften hinzufügen können, können Sie die bereits vorhandenen Eigenschaften nicht ändern
Ein Screenshot eines Tests in der Chrome-Konsole
Zusammenfassend ist 1. der gesamte Wert des Zeichenfolgentyps (primitiver Typ) unveränderlich. 2. Das String-Objekt ist veränderbar, aber der darin enthaltene String-Typ-Wert (primitiver Typ) ist unveränderlich.
quelle
new String
erzeugt einen veränderlichen Wrapper um einen unveränderlichen StringString
Objekt (Wrapper) vollständig neue Eigenschaften hinzufügen , was bedeutet, dass es nicht unveränderlich ist (standardmäßig; wie jedes andere Objekt, das Sie aufrufenObject.freeze
können, um es unveränderlich zu machen). Ein primitiver Zeichenfolgenwerttyp, unabhängig davon, ob er in einemString
Objektwrapper enthalten ist oder nicht, ist immer unveränderlich.Saiten sind unveränderlich - sie können sich nicht ändern, wir können immer nur neue Saiten erstellen.
Beispiel:
quelle
In Bezug auf Ihre Frage (in Ihrem Kommentar zu Ashs Antwort) zum StringBuilder in ASP.NET Ajax scheinen sich die Experten in dieser Frage nicht einig zu sein.
Christian Wenz sagt in seinem Buch Programming ASP.NET AJAX (O'Reilly), dass "dieser Ansatz keine messbaren Auswirkungen auf das Gedächtnis hat (tatsächlich scheint die Implementierung ein Tick langsamer zu sein als der Standardansatz)."
Auf der anderen Seite sagen Gallo et al. In ihrem Buch ASP.NET AJAX in Action (Manning): "Wenn die Anzahl der zu verkettenden Zeichenfolgen größer ist, wird der Zeichenfolgengenerator zu einem wesentlichen Objekt, um enorme Leistungseinbußen zu vermeiden."
Ich denke, Sie müssten Ihr eigenes Benchmarking durchführen, und die Ergebnisse können auch zwischen den Browsern unterschiedlich sein. Selbst wenn es die Leistung nicht verbessert, kann es dennoch als "nützlich" für Programmierer angesehen werden, die es gewohnt sind, mit StringBuilders in Sprachen wie C # oder Java zu codieren.
quelle
Es ist ein später Beitrag, aber ich habe unter den Antworten kein gutes Buchzitat gefunden.
Hier ist eine eindeutige Ausnahme von einem zuverlässigen Buch:
Die Antwort, die den Auszug aus dem Rhino-Buch zitiert, ist richtig in Bezug auf die Unveränderlichkeit von Zeichenfolgen, aber falsch: "Zeichenfolgen werden durch Referenz und nicht durch Wert zugewiesen." (wahrscheinlich wollten sie die Wörter ursprünglich anders ausdrücken).
Das Missverständnis "Referenz / Wert" wird im Kapitel "Professionelles JavaScript" im Kapitel "Primitive und Referenzwerte" erläutert:
das ist gegen Objekte :
quelle
JavaScript-Zeichenfolgen sind in der Tat unveränderlich.
quelle
Zeichenfolgen in Javascript sind unveränderlich
quelle