String-Objekten per prototype trim()-Methode geben
Felix Riesterer
- javascript
Liebe JavaScript-Spezialisten,
man lernt immer wieder dazu, und so wollte ich mir heute aus Bequemlichkeit eine trim()-Funktion schneidern, wie ich sie von PHP her kenne. Da es bequemer ist, den Punkt-Operator zu benutzen (myString = myString.trim();
) anstatt eine Methode eines fremden Objekts und Werteübergabe zu bemühen (myString = meineSuperTools.stringTrimmer(myString);
, dachte ich an den Gebrauch der Prototypisierung.
Das ist mein erstes Mal, daher dieses Posting.
Ist es bei Strings normal, dass ich im Firefox mit einer for-in-Schleife keine der String-Methoden ausgeben lassen kann, die einem String-Objekt von Hause aus mitgegeben werden? Ich habe nämlich die "Werteübergabe" mit "this" gelöst, weiß jetzt aber nicht, ob das immer beim Prototypisieren klappt. Mein Code sieht so aus:
// Nur prototypisieren, falls Methode nicht verfügbar:
if (typeof(new String().trim()) != "function") {
String.prototype.trim = function () {
var s = this.toString();
s = s.replace(/^ +/, "");
s = s.replace(/ +$/, "");
return s;
}
}
Die, die Ihr mehr Erfahrung damit habt, ist obiges Beispiel aus Eurer Sicht unproblematisch, oder könnte es schwerwiegende Probleme damit geben, wenn man das Script mit anderen Scripten oder gar "Bibliotheken" (oder gar "Frameworks") benutzt?
Liebe Grüße aus Ellwangen,
Felix Riesterer.
s = s.replace(/^ +/, "");
s = s.replace(/ +$/, "");
Das ist natürlich Quatsch, wenn es der trim()-Funktion von PHP nachempfunden sein soll. Korrektur:
// Nur prototypisieren, falls Methode nicht verfügbar:
if (typeof(new String().trim()) != "function") {
String.prototype.trim = function () {
var s = this.toString();
s = s.replace(/^[ \t\r\n]+/, "");
s = s.replace(/[ \t\r\n]+$/g, "");
return s;
}
}
Liebe Grüße aus Ellwangen,
Felix Riesterer.
// Nur prototypisieren, falls Methode nicht verfügbar:
if (typeof(new String().trim) != "function") {
String.prototype.trim = function () {
var s = this.toString();
s = s.replace(/^[ \t\r\n]+/, "");
s = s.replace(/[ \t\r\n]+$/g, "");
return s;
}
}
Liebe Grüße aus Ellwangen,
Felix Riesterer.
// Nur prototypisieren, falls Methode nicht verfügbar:
if (typeof(new String().trim()) != "function") {
if(typeof String.prototype.trim != 'function'){
}
String.prototype.trim = function () {
var s = this.toString();
Du musst wohl nicht einen String in einen String umwandeln.
s = s.replace(/^ +/, "");
s = s.replace(/ +$/, "");
Bei mir sieht das so aus:
[code lang=javascript]String.prototype.trim = function ()
{
if(!this.length) return "";
return this.ltrim().rtrim();
}
String.prototype.rtrim = function ()
{
if(!this.length) return "";
return this.replace(/\s+$/g, '');
}
String.prototype.ltrim = function ()
{
if(!this.length) return "";
return this.replace(/^\s+/g, '');
}
> Die, die Ihr mehr Erfahrung damit habt, ist obiges Beispiel aus Eurer Sicht unproblematisch, oder könnte es schwerwiegende Probleme damit geben, wenn man das Script mit anderen Scripten oder gar "Bibliotheken" (oder gar "Frameworks") benutzt?
Ich hab wenig Erfahrung mit Frameworks, aber warum sollte es Probleme geben?
Struppi.
gruss Felix, hallo Struppi,
/*
ich entwickle solche funktionalitaet
mittlerweile lieber so: */
if (typeof String.prototype.trim != "function") {
String.prototype.trim = (function () {
var regXTrim = (/^\s+|\s+$/g);
return (function () {
return this.replace(regXTrim, "");
});
})();
}/*
anstatt so: */
if (typeof String.prototype.trim != "function") {
String.prototype.trim = (function () {
return this.replace((/^\s+|\s+$/g), "");
});
}/*
fuer die zweite loesung wird der regulaere ausdruck bei jedem
aufruf der [trim]-methode neu initialisiert(/kompiliert) und
nach abarbeitung der methode wieder verworfen.
die zweite loesung legt diesen konstanten regulaeren ausdruck
nur einmal im funktionsstack der aeusseren erzeugerfunktion an
sobald diese ausgefuehrt wird und gibt dabei auch die [trim]-
methode zurueck, welche immer zugriff auf den unveraenderlichen
ausdruck hat, da sie zusammen mit diesem im selben sichtbarkeits-
(speicher)bereich erzeugt wurde.
in der praxis wird man den geschwindigkeitsvorteil der ersten
gegenueber der zweiten loesung aber wohl kaum wahrnehmen koennen.
*/
so long - peterS. - pseliger@gmx.net
Hallo,
in der praxis wird man den geschwindigkeitsvorteil der ersten
gegenueber der zweiten loesung aber wohl kaum wahrnehmen koennen.
Ich würde sogar behauptet, dass JavaScript-Interpreter sowas wegoptimieren. Aber müsste man mal untersuchen.
»if you use literal notation to construct a regular expression used in a loop, the regular expression won't be recompiled on each iteration.«
Aus JavaScript 1.3, bezog sich auf Netscape 4...
Mathias
你好 molily,
in der praxis wird man den geschwindigkeitsvorteil der ersten
gegenueber der zweiten loesung aber wohl kaum wahrnehmen koennen.Ich würde sogar behauptet, dass JavaScript-Interpreter sowas wegoptimieren. Aber müsste man mal untersuchen.
Würde ich auch von ausgehen, das ist eine der einfachsten möglichen Optimierungsmethoden. Ich wäre sehr überrascht, wenn das nicht optimiert würde.
Nicht so einfach optimiert werden könnte dagegen etwas wie re = RegExp.new("/some regex/");
.
再见,
克里斯蒂安
Hallo,
Nicht so einfach optimiert werden könnte dagegen etwas wie
re = RegExp.new("/some regex/");
.
Ja, das wird auch in JavaScript 1.3 angesprochen:
»The constructor of the regular expression object, for example, new RegExp("ab+c"), provides runtime compilation of the regular expression. Use the constructor function when you know the regular expression pattern will be changing, or you don't know the pattern and are getting it from another source, such as user input.«
http://devedge-temp.mozilla.org/library/manuals/2000/javascript/1.3/reference/regexp.html
Mathias
[latex]Moin![/latex]
if(typeof String.prototype.trim != 'function'){
}
Da ich es eigentlich ständig wie oben lese:
Ist es sinnvoll und ausreichend, so spezifisch wie oben auf != "function"
abzufragen?
Nehmen wir mal an, jemand kopiert sich die Methode trim in sein Script, hat aber einen Scriptteil, in dem (ist in diesem Falle mit dem Namen trim unwahrscheinlich, kann aber bei anderen Namen durchaus sein) eine Eigenschaft trim für das String-Objekt definiert. Schon ist != "function"
"true" und die Eigenschaft wird überschrieben.
Wäre es nicht sicherer, auf "undefined" zu testen?
Cü,
Kai
你好 Kai345,
Nehmen wir mal an, jemand kopiert sich die Methode trim in sein Script, hat aber einen Scriptteil, in dem (ist in diesem Falle mit dem Namen trim unwahrscheinlich, kann aber bei anderen Namen durchaus sein) eine Eigenschaft trim für das String-Objekt definiert. Schon ist
!= "function"
"true" und die Eigenschaft wird überschrieben.Wäre es nicht sicherer, auf "undefined" zu testen?
Wenn du eine allgemeingültige Bibliothek schreiben willst, würde man ein Namensmuster definieren, indem man solche Erweiterungen implementiert. Derjenige, der diese Bibliothek einsetzt, weiss das dann und hält sich daran.
Macht man es nur für ein Script, wäre es ein Bug, wenn man in .trim etwas reinschreibt und etwas später wieder überschreibt.
Ich halte diese Überprüfung für völlig ausreichend, der einzige Fall, der hier auftreten kann, in dem man nicht überschreiben will, ist der, dass es aus irgendwelchen Gründen bereits eine Funktion gibt, z. B. weil sie nativ eingebaut ist.
再见,
克里斯蒂安
[latex]Moin![/latex]
Wäre es nicht sicherer, auf "undefined" zu testen?
[...]
Macht man es nur für ein Script, wäre es ein Bug, wenn man in .trim etwas reinschreibt und etwas später wieder überschreibt.
Ich halte diese Überprüfung für völlig ausreichend, der einzige Fall, der hier auftreten kann, in dem man nicht überschreiben will, ist der, dass es aus irgendwelchen Gründen bereits eine Funktion gibt, z. B. weil sie nativ eingebaut ist.
Ach Mist, "Nativ" bringt mich zu dem Teil, auf den ich eigentlich hinauswollte, den ich vergessen habe zu schreiben. Das Alter halt ;)
Nehmen wir an, jemand erweitert sein Javascript mit der Methode String.prototype.foo = function() { .. } und irgendwann in 5 Jahren wird ausgerechnet String.foo offiziell als Eigenschaft definiert und eingeführt. Soche Fälle meine ich unter anderm.
Cü,
Kai
你好 Kai345,
Nehmen wir an, jemand erweitert sein Javascript mit der Methode String.prototype.foo = function() { .. } und irgendwann in 5 Jahren wird ausgerechnet String.foo offiziell als Eigenschaft definiert und eingeführt. Soche Fälle meine ich unter anderm.
In dem Fall will man doch trotzdem, dass die Eigenschaft überschrieben wird. Sonst funktioniert ja das Script nicht mehr.
再见,
克里斯蒂安
Wäre es nicht sicherer, auf "undefined" zu testen?
Das bleibt letztlich dir überlassen, das Problem ist ja, dass dann u.U. dein Skript nicht funktioniert, da du ja eine Methode haben willst, es aber durchaus sein kann dass jemand anderes so eine Methode schon implementiert hat und diese sollte dann auch das tun was du erwartest.
Struppi.
Lieber Struppi,
Bei mir sieht das so aus: [...]
if(!this.length) return "";
warum prüfst Du auf das Vorhandensein von length? Ist das eine Art Sicherheitsvorkehrung gegen Strings, die keine Längeneigenschaft haben? Oder eher gegen eine irrtümliche oder fehlerhafte Verwendung Deiner Methoden?
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Hallo,
warum prüfst Du auf das Vorhandensein von length? Ist das eine Art Sicherheitsvorkehrung gegen Strings, die keine Längeneigenschaft haben? Oder eher gegen eine irrtümliche oder fehlerhafte Verwendung Deiner Methoden?
Was ist wohl rechentechnisch günstiger - eine Überprüfung auf Länge (die ein gutes String-objekt wahrscheinlich nicht jedes Mal neu berechnet) oder ein Matchen gegen einen Regulären Ausdruck? ;)
Tim
你好 Felix,
Bei mir sieht das so aus: [...]
if(!this.length) return "";warum prüfst Du auf das Vorhandensein von length? [...]
if(!this.length) ist das gleiche (nicht dasselbe) wie if(this.length == 0). Klingelts? ;)
再见,
克里斯蒂安
Lieber Christian,
if(!this.length) ist das gleiche (nicht dasselbe) wie if(this.length == 0). Klingelts? ;)
aber dann könnte man doch auch genausogut schreiben return (this == "") ? "" : this.replace(/\s+$/, "");
Liebe Grüße aus Ellwangen,
Felix Riesterer.
你好 Felix,
aber dann könnte man doch auch genausogut schreiben [...]
Klar. Und es gibt noch so einige Wege, wie man es hätte schreiben können. Und?
再见,
克里斯蒂安