String.prototype.endsWith(str) in Javascript

In meinem Projekt bin ich letztens über folgende, doch sehr hässlichen Konstrukte gestolpert:

function onKeypress(element)) {
  if (jQuery(element).attr("id").indexOf(str) != -1)) {
    //dosomething
  }
}

Um hier zu erfassen, dass der Code überprüft, ob die ID eines Elementes einen bestimmten String enthält, braucht man schon etwas länger. Neben dem überflüssigen jQuery-Aufruf, um die ID zu ermitteln, fällt auf, dass hier eine String-Utility-Methode wie [highlight1]contains()[/highlight1], [highlight1]startsWith()[/highlight1] oder [highlight1]endsWith()[/highlight1] nützlich wäre, um die Lesbarkeit des Codes deutlich zu verbessern. Ich habe mich deshalb fix entschlossen, die entsprechenden Methoden Projekt-weit nachzubauen.

Da es im konkreten Beispiel ausreichend war zu überprüfen, ob ein String mit einem anderen String endet, befasse ich mich hier mit [highlight1]String.prototype.endsWith(str)[/highlight1]. Die sehr ähnlichen Methoden [highlight2]contains()[/highlight2] und [highlight2]startsWith()[/highlight2] lassen sich analog umsetzen.

Per Google findet man diverse Methoden wie [highlight1]endsWith()[/highlight1] in Javascript nachzubauen ist. Folgende drei Varianten habe ich mal genauer untersucht:

String.prototype.endsWith1 = function(str) {
  var lastIndex = this.lastIndexOf(str);
  return (lastIndex !== -1) && (lastIndex + str.length === this.length);
};

String.prototype.endsWith2 = function(s) {
  return this.length >= s.length && this.substr(this.length - s.length) === s;
}

String.prototype.endsWith3 = function(str) {
  return (this.match(str + "$") === str)
}

Aufgrund einer Diskussion auf stackoverflow hat mich auch noch interessiert, welche von diesen drei Varianten in modernen Browsern am schnellsten abläuft. Die Auswertung mittels jsperf hat mich dann doch überrascht. Zwar sind die Varianten 1 + 2 browserübergreifend mit geringem Abstand untereinander (aber weit vor Variante 3) am schnellsten, allerdings war Chrome 22 um Größenordnungen langsamer, Firefox war ungefähr 10 mal so schnell!

In mein Projekt eingebaut, habe ich dann Variante 1. Und um sicherzugehen, eine eventuell schon vorhandene Methode am String-Prototypen nicht versehentlich zu überschreiben, sollte man natürlich vorher noch überprüfen, ob der String-Prototyp nicht schon so eine Methode hat. Der komplette Code sieht so aus:

if (!String.prototype.hasOwnProperty("endsWith")) {
  String.prototype.endsWith = function(str) {
    var lastIndex = this.lastIndexOf(str);
    return (lastIndex !== -1) && (lastIndex + str.length === this.length);
  };
}

Obiges Beispiel im richtigen Code, sieht dann damit viel schöner aus:

function onKeypress(element)) {
  if (element.id.endsWith(str)) {
    //dosomething
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *


*