Category Archives: Javascript

Crockford on Javascript

Wer noch nie einen Vortrag von Douglas Crockford gesehen hat, dem empfehle ich ganz herzlich seine “Crockford on Javascript” Vorträge auf Youtube.

Douglas Crockford war lange Zeit Javascript Evangelist bei Yahoo und ist der Entdecker des JSON-Formats. Übrigens Entdecker und nicht Erfinder, denn wie er selbst mal in einem Vortrag hervorgehoben hat, musste dieses Format quasi in Javascript entdeckt werden, weil es elementarer Teil der Sprache ist.

Ich finde seine Vorträge äusserst faszinierend, wirken sie doch eigentlich extrem trocken, aber sehr fundiert und sind dann doch immer wieder mit zahlreichen Spitzen garniert. Neben zahlreichen Anekdoten, kann man eine Menge als Javascript-Entwickler lernen.

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
  }
}