Wie überprüfe ich, ob eine Zeichenfolge mit einer anderen Zeichenfolge beginnt?

1690

Wie würde ich das Äquivalent von C # String.StartsWithin JavaScript schreiben ?

var haystack = 'hello world';
var needle = 'he';

haystack.startsWith(needle) == true

Hinweis: Dies ist eine alte Frage, und wie in den Kommentaren ausgeführt, wurde ECMAScript 2015 (ES6) die .startsWithMethode eingeführt. Zum Zeitpunkt des Schreibens dieses Updates (2015) ist die Browserunterstützung jedoch noch lange nicht abgeschlossen .

Luca Kiebel
quelle

Antworten:

1773

Sie können die String.prototype.startsWith()Methode von ECMAScript 6 verwenden, sie wird jedoch noch nicht in allen Browsern unterstützt . Sie sollten ein Shim / Polyfill verwenden, um es in Browsern hinzuzufügen, die es nicht unterstützen. Das Erstellen einer Implementierung, die allen in der Spezifikation angegebenen Details entspricht, ist etwas kompliziert. Wenn Sie eine originalgetreue Unterlegscheibe wünschen, verwenden Sie entweder:

Sobald Sie die Methode angepasst haben (oder wenn Sie nur Browser und JavaScript-Engines unterstützen, die sie bereits haben), können Sie sie folgendermaßen verwenden:

"Hello World!".startsWith("He"); // true

var haystack = "Hello world";
var prefix = 'orl';
haystack.startsWith(prefix); // false
CMS
quelle
@gtournie warum sollte StartsWith eine der schlechtesten Methoden sein, um zu testen, ob eine Zeichenfolge mit einer Zeichenfolge beginnt? (Siehe Ihren Kommentar hier: stackoverflow.com/questions/646628/… ) Sie sind mehr begeistert davon, Zeichen pro Zeichen zu vergleichen. Ich hoffe, Compiler sind klug genug, NICHT für jede Zeichenfolge [Index] eine Zeichenfolge zu generieren, denn wenn Sie einfach Folgendes schreiben: Zeichen = Zeichenfolge [0], wird ein Objekt zugewiesen, das unendlich WENIGER effizient ist als die Verwendung von StartsWith (StartsWith weist keinen Speicher zu )
Martijn Scheffer
@MartijnScheffer: Die Antwort wurde seit meiner Antwort viele Male bearbeitet und ist jetzt völlig anders (ich habe meinen Kommentar entfernt;). Ich bin damit einverstanden, dass die StartsWith-Methode von ECMAScript 6 der beste Weg ist, dies zu tun.
Gtournie
6
@GrahamLaight, wenn Sie sagen, unterstützt von 'IE', meinen Sie vermutlich mit Edge. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Marcus
@Marcus, entschuldige mich, wenn ich falsch lag - meine Informationen kamen von: w3schools.com/jsref/jsref_startswith.asp
Graham Laight
WARNUNG! Diese jsperf-Tests funktionieren nicht in Browsern, die sich gut mit JIT kompilieren lassen. Browser wie Firefox und Chrome erkennen es manchmal, wenn das Ergebnis eines Vorgangs verworfen wird, und führen den Vorgang daher nicht aus . Abgesehen davon verwenden moderne Javascript-Engines die Verzweigungsvorhersage , sodass die Testzeichenfolgen in jeder Iteration unterschiedlich sein sollten.
Aloso
1283

Eine andere Alternative mit .lastIndexOf:

haystack.lastIndexOf(needle, 0) === 0

Dies sieht rückwärts haystacknach einem Auftreten needleaus, das mit dem Index 0von beginnt haystack. Mit anderen Worten, es wird nur geprüft, ob mit haystackbeginnt needle.

Im Prinzip sollte dies Leistungsvorteile gegenüber einigen anderen Ansätzen haben:

  • Es wird nicht das gesamte durchsucht haystack.
  • Es wird keine neue temporäre Zeichenfolge erstellt und diese dann sofort verworfen.
Mark Byers
quelle
1
Ich bin mir nicht sicher, welchen Fall @ rfcoder89 in Angriff nimmt - jsfiddle.net/jkzjw3w2/1
Gulfaraz Rahman
5
@ rfcoder89 Beachten Sie, dass der zweite Parameter von lastIndexOf: "aba".lastIndexOf ("a")2 ist, wie Sie hervorheben , aber "aba".lastIndexOf ("a", 0)0 ist, was richtig ist
maxpolk
1
Ich danke dir sehr. String.startsWith funktioniert nicht mit Android Lollipop WebView, aber dieses lastIndexOf-Snippet funktioniert !!!
Herman
Mit lastIndexOf wird die Zeichenfolge vom Ende bis zum Anfang durchsucht, sodass die gesamte Zeichenfolge durchsucht wird.
Daher
8
@willywonka Nein, es ist nicht, wenn Sie 0 startIndex haben, es wird von 0 pos gesucht und es ist die einzige Prüfung. Die gesamte Zeichenfolge wird nur durchsucht, wenn fromIndex> = str.length.
Greene
588
data.substring(0, input.length) === input
Cobbal
quelle
3
@ ANeves Ich vermute, es hängt stark vom Browser und den verwendeten Daten ab. Die tatsächlichen Messungen finden Sie in der Antwort von Ben Weaver. Auf dem Browser, den ich derzeit ausführe (Chrome 12.0.742 unter Windows), gewinnt die Teilzeichenfolge für den Erfolg und die vorbereiteten regulären Ausdrücke für den Fehler.
Cobbal
4
@ Cobbal Vielleicht. Aber .lastIndexOf(input, 0)vergleicht die ersten N Zeichen, während die .substring(0, input.length) === inputZählwerte N, Teilketten die Daten auf N Länge und vergleicht dann diese N Zeichen. Ohne zweite Codeoptimierung kann diese zweite Version nicht schneller sein als die andere. Versteh mich nicht falsch, ich würde niemals etwas Besseres finden, als du vorgeschlagen hast. :)
ANeves
2
@ANeves Aber .lastIndexOf für eine lange Zeichenfolge, die false zurückgibt, wird über die gesamte Zeichenfolge (O (N)) iteriert, während der Fall .substring über eine möglicherweise viel kleinere Zeichenfolge iteriert. Wenn Sie mehrheitliche Erfolge oder nur kleine Eingaben erwarten, ist .lastIndexOf wahrscheinlich schneller - andernfalls ist .substring wahrscheinlich schneller. .substring riskiert auch eine Ausnahme, wenn die Eingabe länger als die zu prüfende Zeichenfolge ist.
Chris Moschini
14
@ ChrisMoschini, vergessen Sie nicht, dass die Lösung von Mark Byers lastIndexOfbei Index 0 beginnt und nicht am Ende. Das hat mich anfangs auch gestolpert. Das Überprüfen, mit was eine Zeichenfolge beginnt, ist jedoch eine so häufige Aufgabe, dass JavaScript wirklich eine geeignete API dafür haben sollte, nicht alle Redewendungen und Alternativen, die Sie auf dieser Seite sehen, wie clever sie auch sein mögen.
Randall Cook
4
Ich bevorzuge Cobbals Lösung gegenüber Marks. Selbst wenn Markierungen schneller sind und ein beeindruckender Trick mit den Parametern, ist es im Vergleich zu Teilzeichenfolgen sehr schwer zu lesen.
ThinkBonobo
184

Verwenden Sie ohne Hilfsfunktion nur die .testMethode von regex :

/^He/.test('Hello world')

Um dies mit einer dynamischen Zeichenfolge anstelle einer fest codierten Zeichenfolge zu tun (vorausgesetzt, die Zeichenfolge enthält keine regulären Ausdruckssteuerzeichen):

new RegExp('^' + needle).test(haystack)

Sie sollten auschecken Gibt es eine RegExp.escape-Funktion in Javascript? Wenn die Möglichkeit besteht, dass Regexp-Steuerzeichen in der Zeichenfolge angezeigt werden.

Vincent
quelle
1
Um den Ausdruck zwischen Groß- und Kleinschreibung zu machen/^he/i
kaizer1v
64

Beste Lösung:

function startsWith(str, word) {
    return str.lastIndexOf(word, 0) === 0;
}

Und hier endet es, wenn Sie das auch brauchen:

function endsWith(str, word) {
    return str.indexOf(word, str.length - word.length) !== -1;
}

Für diejenigen, die es vorziehen, einen Prototyp in String zu erstellen:

String.prototype.startsWith || (String.prototype.startsWith = function(word) {
    return this.lastIndexOf(word, 0) === 0;
});

String.prototype.endsWith   || (String.prototype.endsWith = function(word) {
    return this.indexOf(word, this.length - word.length) !== -1;
});

Verwendungszweck:

"abc".startsWith("ab")
true
"c".ensdWith("c") 
true

Mit Methode:

startsWith("aaa", "a")
true
startsWith("aaa", "ab")
false
startsWith("abc", "abc")
true
startsWith("abc", "c")
false
startsWith("abc", "a")
true
startsWith("abc", "ba")
false
startsWith("abc", "ab")
true
mmm
quelle
Ich denke, Sie haben lastIndexOf und indexOf in Ihren Funktionen verwechselt - StartsWith sollte str.indexOf (word, 0) === 0 zurückgeben;
Richard Matheson
5
@RichardMatheson Das Problem bei der Verwendung von indexOf besteht darin, dass, wenn die Übereinstimmung beim Start fehlschlägt, die gesamte Zeichenfolge weiter durchsucht wird, wobei lastIndexOf von der Länge des Wortes ausgeht und auf Null zurückgeht. Ich habs?
mmm
2
Ahh ja macht jetzt Sinn - ich habe nicht auf die Indizes geachtet, die Sie verwendet haben. Sehr schöner Trick!
Richard Matheson
54

Ich wollte nur meine Meinung dazu hinzufügen.

Ich denke, wir können einfach so verwenden:

var haystack = 'hello world';
var needle = 'he';

if (haystack.indexOf(needle) == 0) {
  // Code if string starts with this substring
}
Mr.D
quelle
2
Die Antwort von Mark Byers wurde von @relfor auf die Leistung von drei verschiedenen korrekten Ansätzen verglichen. Dieser korrekte Ansatz wurde nicht bevorzugt, da die gesamte Zeichenfolge durchsucht werden muss.
Maxpolk
@maxpolk Ich denke indexOf, die Suche nach der gesamten Zeichenfolge wird beendet, wenn sie zum ersten Mal auftritt. Ich habe es überprüft.
Mr.D
8
Wenn das erste Vorkommen nicht ganz am Anfang gefunden wird, wird dieser Ansatz ineffizienter, je länger er danach sucht und möglicherweise bis zum Ende sucht, anstatt viel früher aufzugeben. Da das Potenzial für Ineffizienz besteht, wird es unter den drei richtigen Ansätzen nicht bevorzugt.
Maxpolk
2
@ Mr.D Und wenn es keine Übereinstimmung gibt?
mmm
sonst, wenn der gesamte Heuhaufen durchsucht wurde? ist besser: stackoverflow.com/a/36876507/961018 .. sucht nur bis zur Wortlänge
mmm
39

Hier ist eine kleine Verbesserung der CMS-Lösung:

if(!String.prototype.startsWith){
    String.prototype.startsWith = function (str) {
        return !this.indexOf(str);
    }
}

"Hello World!".startsWith("He"); // true

 var data = "Hello world";
 var input = 'He';
 data.startsWith(input); // true

Überprüfen, ob die Funktion bereits vorhanden ist, falls ein zukünftiger Browser sie in nativem Code implementiert oder von einer anderen Bibliothek implementiert wird. Beispielsweise implementiert die Prototypbibliothek diese Funktion bereits.

Die Verwendung !ist etwas schneller und prägnanter als === 0nicht so lesbar.

Kit
quelle
1
Dies könnte zu einem Problem werden: Wenn sich die bereits vorhandene Implementierung anders verhält als meine eigene, würde dies meine Anwendung beschädigen.
Christoph Wurm
2
Dies hat das O (N) Problem hier diskutiert stackoverflow.com/questions/646628/javascript-startswith/…
Chris Moschini
1
mit! Es ist sehr chaotisch
JonnyRaa
-1; Dies hinzuzufügen String.prototypeist eine schlechte Idee, da es nicht annähernd der Spezifikation für entspricht String.prototype.startsWith. Jeder Code, der versucht, die ES6-Methode zu verwenden, kann in diesem Fall fehlschlagen. Möglicherweise wird geprüft, ob die Methode bereits definiert ist, ob sie (schlecht von Ihnen) vorliegt, und es wird kein spezifikationskonformer Shim hinzugefügt, was später zu falschem Verhalten führt.
Mark Amery
21

Schauen Sie sich auch underscore.string.js an . Es enthält eine Reihe nützlicher Methoden zum Testen und Bearbeiten von Zeichenfolgen, einschließlich einer startsWithMethode. Aus den Dokumenten:

beginnt mit _.startsWith(string, starts)

Diese Methode prüft, ob mit stringbeginnt starts.

_("image.gif").startsWith("image")
=> true
studgeek
quelle
1
Ich brauchte_.string.startsWith
Colonel Panic
15

Ich habe mir kürzlich die gleiche Frage gestellt.
Es gibt mehrere mögliche Lösungen, hier sind 3 gültige:

  • s.indexOf(starter) === 0
  • s.substr(0,starter.length) === starter
  • s.lastIndexOf(starter, 0) === 0(hinzugefügt, nachdem Mark Byers ' Antwort gesehen wurde )
  • mit einer Schleife:

    function startsWith(s,starter) {
      for (var i = 0,cur_c; i < starter.length; i++) {
        cur_c = starter[i];
        if (s[i] !== starter[i]) {
          return false;
        }
      }
      return true;
    }

Ich bin nicht auf die letzte Lösung gestoßen, die eine Schleife verwendet.
Überraschenderweise übertrifft diese Lösung die ersten 3 deutlich.
Hier ist der jsperf-Test, den ich durchgeführt habe, um zu dieser Schlussfolgerung zu gelangen: http://jsperf.com/startswith2/2

Frieden

ps: ecmascript 6 (Harmonie) führt eine native startsWithMethode für Zeichenfolgen ein.
Stellen Sie sich vor, wie viel Zeit gespart worden wäre, wenn sie daran gedacht hätten, diese dringend benötigte Methode in die ursprüngliche Version selbst aufzunehmen.

Aktualisieren

Wie Steve betonte (der erste Kommentar zu dieser Antwort), wird die obige benutzerdefinierte Funktion einen Fehler auslösen, wenn das angegebene Präfix kürzer als die gesamte Zeichenfolge ist. Er hat das behoben und eine Schleifenoptimierung hinzugefügt, die unter http://jsperf.com/startswith2/4 eingesehen werden kann .

Beachten Sie, dass es zwei Schleifenoptimierungen gibt, die Steve aufgenommen hat. Die erste der beiden zeigte eine bessere Leistung. Daher werde ich diesen Code unten veröffentlichen:

function startsWith2(str, prefix) {
  if (str.length < prefix.length)
    return false;
  for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i)
    continue;
  return i < 0;
}
Raj Nathani
quelle
Siehe die neueste Version. Neben dem Fehler in der obigen Version (der ausgelöst wird, wenn die Zeichenfolge kürzer als das Präfix ist) ist er auch langsamer als eine optimierte Version. Siehe jsperf.com/startswith2/4 und jsperf.com/js-startswith/35 .
Steve Hollasch
^ Vielen Dank für den Hinweis auf den Fall, dass die Zeichenfolge kürzer als das Präfix ist
Raj Nathani
jsperf.com/startswith2/29 => StartsWith5 ist prägnant und funktioniert wirklich gut =)
Gtournie
11

Da dies so beliebt ist, sollte darauf hingewiesen werden, dass es eine Implementierung für diese Methode in ECMA 6 gibt. In Vorbereitung darauf sollte die „offizielle“ Polyfüllung verwendet werden, um zukünftige Probleme und Tränen zu vermeiden.

Zum Glück stellen uns die Experten von Mozilla eines zur Verfügung:

https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith

if (!String.prototype.startsWith) {
    String.prototype.startsWith = function(searchString, position) {
        position = position || 0;
        return this.indexOf(searchString, position) === position;
    };
}

Bitte beachten Sie, dass dies den Vorteil hat, dass es beim Übergang zu ECMA 6 ordnungsgemäß ignoriert wird.

Scheintod
quelle
5

Die beste Lösung besteht darin, die Verwendung von Bibliotheksaufrufen zu beenden und nur zu erkennen, dass Sie mit zwei Arrays arbeiten. Eine handgerollte Implementierung ist sowohl kurz als auch schneller als jede andere Lösung, die ich hier gesehen habe.

function startsWith2(str, prefix) {
    if (str.length < prefix.length)
        return false;
    for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i)
        continue;
    return i < 0;
}

Leistungsvergleiche (Erfolg und Misserfolg) finden Sie unter http://jsperf.com/startswith2/4 . (Stellen Sie sicher, dass Sie nach späteren Versionen suchen, die meine möglicherweise übertrumpft haben.)

Steve Hollasch
quelle
2

Ich habe gerade von dieser String-Bibliothek erfahren:

http://stringjs.com/

Fügen Sie die js-Datei ein und verwenden Sie die SVariable wie folgt :

S('hi there').endsWith('hi there')

Es kann auch in NodeJS verwendet werden, indem es installiert wird:

npm install string

Dann benötigen Sie es als SVariable:

var S = require('string');

Die Webseite enthält auch Links zu alternativen Zeichenfolgenbibliotheken, falls Sie dies nicht möchten.

Ashley Davis
quelle
2
  1. Die Frage ist etwas alt, aber ich wollte diese Antwort schreiben, um Ihnen einige Benchmarks zu zeigen, die ich basierend auf allen hier gegebenen Antworten und dem von Jim Buck geteilten jsperf erstellt habe.

Ich brauchte im Grunde einen schnellen Weg, um herauszufinden, ob sich eine lange Nadel in einem langen Heuhaufen befindet und sie bis auf die letzten Zeichen sehr ähnlich sind.

Hier ist der Code, den ich geschrieben habe und der für jede Funktion (Spleiß, Teilzeichenfolge, StartsWith usw.) beide Tests durchführt, wenn sie falsch und wahr gegen eine Heuhaufenzeichenfolge ( nestedString) mit 1.000.0001 Zeichen und eine falsche oder wahrheitsgemäße Nadelzeichenfolge mit 1.000.000 Zeichen zurückgeben Zeichen ( testParentStringFalseund testParentStringTruesind):

// nestedString is made of 1.000.001 '1' repeated characters.
var nestedString = '...'

// testParentStringFalse is made of 1.000.000 characters,
// all characters are repeated '1', but the last one is '2',
// so for this string the test should return false.
var testParentStringFalse = '...'

// testParentStringTrue is made of 1.000.000 '1' repeated characters,
// so for this string the test should return true.
var testParentStringTrue = '...'

// You can make these very long strings by running the following bash command
// and edit each one as needed in your editor
// (NOTE: on OS X, `pbcopy` copies the string to the clipboard buffer,
//        on Linux, you would probably need to replace it with `xclip`):
// 
//     printf '1%.0s' {1..1000000} | pbcopy
// 

function testString() {
    let dateStart
    let dateEnd
    let avg
    let count = 100000
    const falseResults = []
    const trueResults = []

    /* slice */
    console.log('========> slice')
    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.slice(0, testParentStringFalse.length) === testParentStringFalse
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    falseResults[falseResults.length] = {
        label: 'slice',
        avg
    }
    console.log(`testString() slice = false`, res, 'avg: ' + avg + 'ms')

    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.slice(0, testParentStringTrue.length) === testParentStringTrue
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    trueResults[trueResults.length] = {
        label: 'slice',
        avg
    }
    console.log(`testString() slice = true`, res, 'avg: ' + avg + 'ms')
    console.log('<======== slice')
    console.log('')
    /* slice END */

    /* lastIndexOf */
    console.log('========> lastIndexOf')
    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.lastIndexOf(testParentStringFalse, 0) === 0
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    falseResults[falseResults.length] = {
        label: 'lastIndexOf',
        avg
    }
    console.log(`testString() lastIndexOf = false`, res, 'avg: ' + avg + 'ms')

    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.lastIndexOf(testParentStringTrue, 0) === 0
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    trueResults[trueResults.length] = {
        label: 'lastIndexOf',
        avg
    }
    console.log(`testString() lastIndexOf = true`, res, 'avg: ' + avg + 'ms')
    console.log('<======== lastIndexOf')
    console.log('')
    /* lastIndexOf END */

    /* indexOf */
    console.log('========> indexOf')
    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.indexOf(testParentStringFalse) === 0
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    falseResults[falseResults.length] = {
        label: 'indexOf',
        avg
    }
    console.log(`testString() indexOf = false`, res, 'avg: ' + avg + 'ms')

    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.indexOf(testParentStringTrue) === 0
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    trueResults[trueResults.length] = {
        label: 'indexOf',
        avg
    }
    console.log(`testString() indexOf = true`, res, 'avg: ' + avg + 'ms')
    console.log('<======== indexOf')
    console.log('')
    /* indexOf END */

    /* substring */
    console.log('========> substring')
    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.substring(0, testParentStringFalse.length) === testParentStringFalse
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    falseResults[falseResults.length] = {
        label: 'substring',
        avg
    }
    console.log(`testString() substring = false`, res, 'avg: ' + avg + 'ms')

    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.substring(0, testParentStringTrue.length) === testParentStringTrue
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    trueResults[trueResults.length] = {
        label: 'substring',
        avg
    }
    console.log(`testString() substring = true`, res, 'avg: ' + avg + 'ms')
    console.log('<======== substring')
    console.log('')
    /* substring END */

    /* startsWith */
    console.log('========> startsWith')
    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.startsWith(testParentStringFalse)
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    falseResults[falseResults.length] = {
        label: 'startsWith',
        avg
    }
    console.log(`testString() startsWith = false`, res, 'avg: ' + avg + 'ms')

    dateStart = +new Date()
    var res
    for (let j = 0; j < count; j++) {
        res = nestedString.startsWith(testParentStringTrue)
    }
    dateEnd = +new Date()
    avg = (dateEnd - dateStart)/count
    trueResults[trueResults.length] = {
        label: 'startsWith',
        avg
    }
    console.log(`testString() startsWith = true`, res, 'avg: ' + avg + 'ms')
    console.log('<======== startsWith')
    console.log('')
    /* startsWith END */

    falseResults.sort((a, b) => a.avg - b.avg)
    trueResults.sort((a, b) => a.avg - b.avg)

    console.log('false results from fastest to slowest avg:', falseResults)
    console.log('true results from fastest to slowest avg:', trueResults)
}

Ich habe diesen Benchmark-Test auf Chrome 75 , Firefox 67 , Safari 12 und Opera 62 durchgeführt .

Ich habe Edge und IE nicht eingeschlossen, weil ich sie nicht auf diesem Computer habe, aber wenn jemand von Ihnen das Skript gegen Edge und mindestens IE 9 ausführen und die Ausgabe hier teilen möchte, wäre ich sehr gespannt auf die Ergebnisse.

Denken Sie daran, dass Sie die 3 langen Zeichenfolgen neu erstellen und das Skript in einer Datei speichern müssen, die Sie dann in Ihrem Browser öffnen, da das Kopieren / Einfügen auf der Browserkonsole es blockiert, da die Länge jeder Zeichenfolge> = 1.000.000 ist.

Hier sind die Ausgänge:

Chrome 75 ( substringgewinnt):

false results from fastest to slowest avg:
1)  {"label":"substring","avg":0.08271}
2)  {"label":"slice","avg":0.08615}
3)  {"label":"lastIndexOf","avg":0.77025}
4)  {"label":"indexOf","avg":1.64375}
5)  {"label":"startsWith","avg":3.5454}

true results from fastest to slowest avg:
1)  {"label":"substring","avg":0.08213}
2)  {"label":"slice","avg":0.08342}
3)  {"label":"lastIndexOf","avg":0.7831}
4)  {"label":"indexOf","avg":0.88988}
5)  {"label":"startsWith","avg":3.55448}

Firefox 67 ( indexOfgewinnt):

false results from fastest to slowest avg
1)  {"label":"indexOf","avg":0.1807}
2)  {"label":"startsWith","avg":0.74621}
3)  {"label":"substring","avg":0.74898}
4)  {"label":"slice","avg":0.78584}
5)  {"label":"lastIndexOf","avg":0.79668}

true results from fastest to slowest avg:
1)  {"label":"indexOf","avg":0.09528}
2)  {"label":"substring","avg":0.75468}
3)  {"label":"startsWith","avg":0.76717}
4)  {"label":"slice","avg":0.77222}
5)  {"label":"lastIndexOf","avg":0.80527}

Safari 12 ( slicegewinnt für falsche Ergebnisse, startsWithgewinnt für echte Ergebnisse, auch Safari ist die schnellste Zeit in Bezug auf die Gesamtzeit, um den gesamten Test auszuführen):

false results from fastest to slowest avg:
1) "{\"label\":\"slice\",\"avg\":0.0362}"
2) "{\"label\":\"startsWith\",\"avg\":0.1141}"
3) "{\"label\":\"lastIndexOf\",\"avg\":0.11512}"
4) "{\"label\":\"substring\",\"avg\":0.14751}"
5) "{\"label\":\"indexOf\",\"avg\":0.23109}"

true results from fastest to slowest avg:
1) "{\"label\":\"startsWith\",\"avg\":0.11207}"
2) "{\"label\":\"lastIndexOf\",\"avg\":0.12196}"
3) "{\"label\":\"substring\",\"avg\":0.12495}"
4) "{\"label\":\"indexOf\",\"avg\":0.33667}"
5) "{\"label\":\"slice\",\"avg\":0.49923}"

Opera 62 ( substringgewinnt. Die Ergebnisse ähneln Chrome und ich bin nicht überrascht, da Opera auf Chromium und Blink basiert):

false results from fastest to slowest avg:
{"label":"substring","avg":0.09321}
{"label":"slice","avg":0.09463}
{"label":"lastIndexOf","avg":0.95347}
{"label":"indexOf","avg":1.6337}
{"label":"startsWith","avg":3.61454}

true results from fastest to slowest avg:
1)  {"label":"substring","avg":0.08855}
2)  {"label":"slice","avg":0.12227}
3)  {"label":"indexOf","avg":0.79914}
4)  {"label":"lastIndexOf","avg":1.05086}
5)  {"label":"startsWith","avg":3.70808}

Es stellt sich heraus, dass jeder Browser seine eigenen Implementierungsdetails hat (abgesehen von Opera, das auf Chrome Chromium und Blink basiert).

Natürlich könnten und sollten weitere Tests mit verschiedenen Anwendungsfällen durchgeführt werden (z. B. wenn die Nadel im Vergleich zum Heuhaufen wirklich kurz ist, wenn der Heuhaufen kürzer als die Nadel ist usw.), aber in meinem Fall musste ich sehr lange Saiten und vergleichen wollte es hier teilen.

Tonix
quelle
1
var str = 'hol';
var data = 'hola mundo';
if (data.length >= str.length && data.substring(0, str.length) == str)
    return true;
else
    return false;
Chris
quelle
0

Basierend auf den Antworten hier ist dies die Version, die ich jetzt verwende, da sie die beste Leistung basierend auf JSPerf-Tests zu bieten scheint (und soweit ich das beurteilen kann, funktional vollständig ist).

if(typeof String.prototype.startsWith != 'function'){
    String.prototype.startsWith = function(str){
        if(str == null) return false;
        var i = str.length;
        if(this.length < i) return false;
        for(--i; (i >= 0) && (this[i] === str[i]); --i) continue;
        return i < 0;
    }
}

Dies basierte auf StartsWith2 von hier: http://jsperf.com/startswith2/6 . Ich habe eine kleine Optimierung für eine kleine Leistungsverbesserung hinzugefügt und seitdem auch eine Überprüfung hinzugefügt, ob die Vergleichszeichenfolge null oder undefiniert ist, und sie konvertiert, um sie mithilfe der in der CMS-Antwort verwendeten Technik zum String-Prototyp hinzuzufügen.

Beachten Sie, dass diese Implementierung den auf dieser Mozilla Developer Network- Seite erwähnten Parameter "position" nicht unterstützt , der jedoch ohnehin nicht Teil des ECMAScript-Vorschlags zu sein scheint.

Edward Millen
quelle
0

Ich bin mir nicht sicher für Javascript, aber in Typoskript habe ich so etwas gemacht

var str = "something";
(<String>str).startsWith("some");

Ich denke, es sollte auch auf js funktionieren. Ich hoffe, es hilft!

Andreas Hadjithoma
quelle
-2

Wenn Sie mit arbeiten startsWith()und endsWith()dann müssen Sie vorsichtig sein, wenn Sie Leerzeichen führen. Hier ist ein vollständiges Beispiel:

var str1 = " Your String Value Here.!! "; // Starts & ends with spaces    
if (str1.startsWith("Your")) { }  // returns FALSE due to the leading spaces…
if (str1.endsWith("Here.!!")) { } // returns FALSE due to trailing spaces…

var str2 = str1.trim(); // Removes all spaces (and other white-space) from start and end of `str1`.
if (str2.startsWith("Your")) { }  // returns TRUE
if (str2.endsWith("Here.!!")) { } // returns TRUE
immayankmodi
quelle
3
Dies ist ein sehr ungewöhnliches Verhalten: Die Zeichenfolge "abc" beginnt NICHT mit "abc". Insbesondere nimmt ECMA 6 keine Art von String-Trimmen an, sodass Leerzeichen genau übereinstimmen müssen, um eine Starts mit Übereinstimmung zu erzielen.
Steve Hollasch
3
Was ... wie beantwortet das die Frage?
DCShannon
1
@DCShannon ist es nicht. Es ist unverständlicher Unsinn.
Mark Amery
2
@SteveHollasch Meine Absicht war es, jemanden zu erkennen, der nach dem gleichen Problem sucht, mit dem ich konfrontiert bin. Dass wir bei der Arbeit mit startsWith()und endsWith()Funktionen vorsichtig mit führenden Räumen umgehen müssen. Nichts anderes!
Immayankmodi
-3

Sie können auch alle Mitglieder eines Arrays zurückgeben, die mit einer Zeichenfolge beginnen, indem Sie einen eigenen Prototyp / eine eigene Erweiterung für den Array-Prototyp erstellen, auch bekannt als

Array.prototype.mySearch = function (target) {
    if (typeof String.prototype.startsWith != 'function') {
        String.prototype.startsWith = function (str){
        return this.slice(0, str.length) == str;
      };
    }
    var retValues = [];
    for (var i = 0; i < this.length; i++) {
        if (this[i].startsWith(target)) { retValues.push(this[i]); }
    }
    return retValues;
};

Und um es zu benutzen:

var myArray = ['Hello', 'Helium', 'Hideout', 'Hamster'];
var myResult = myArray.mySearch('Hel');
// result -> Hello, Helium
Nepaluz
quelle