Felix Riesterer: String-Objekten per prototype trim()-Methode geben

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.

--
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  1. 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.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. // 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.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  2. // 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.
    
    1. 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

      --
      »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
      Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
      ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
      1. 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

        1. 你好 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/");.

          再见,
           克里斯蒂安

          --
          Bauer sucht Frau! | Ich bin ja eigentlich kein Serien-Junkie…
          Gernot Back: Was ich damit sagen will: Dein Gelaber fängt an, sogar mich zu nerven.
          http://wwwtech.de/
          1. 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

    2. [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

      --
      I got sunshine in my stomach, Like I just rocked my baby to sleep.
      I got sunshine in my stomach, But I can't keep me from creeping sleep,
      Sleep, deep in the deep.
      ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|]
      1. 你好 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.

        再见,
         克里斯蒂安

        --
        Bauer sucht Frau! | Ich bin ja eigentlich kein Serien-Junkie…
        Sich erinnern bedeutet, aus einer Erfahrung nicht ausreichend gelernt zu haben.
        http://wwwtech.de/
        1. [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

          --
          I got sunshine in my stomach, Like I just rocked my baby to sleep.
          I got sunshine in my stomach, But I can't keep me from creeping sleep,
          Sleep, deep in the deep.
          ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|]
          1. 你好 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.

            再见,
             克里斯蒂安

            --
            Bauer sucht Frau! | Ich bin ja eigentlich kein Serien-Junkie…
            Mensch zu Mathematiker: "Ich finde Ihre Arbeit ziemlich monoton". Mathematiker: "Mag sein! Dafür ist sie aber stetig und unbeschränkt."
            http://wwwtech.de/
      2. 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.

    3. 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.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      1. 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

      2. 你好 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? ;)

        再见,
         克里斯蒂安

        --
        Bauer sucht Frau! | Ich bin ja eigentlich kein Serien-Junkie…
        Zu wissen, was wir nicht wissen, ist die Quelle der Weisheit.
        http://wwwtech.de/
        1. 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.

          --
          ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
          1. 你好 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?

            再见,
             克里斯蒂安

            --
            Bauer sucht Frau! | Ich bin ja eigentlich kein Serien-Junkie…
            Kommt ein Nullvektor zum Psychiater: "Herr Doktor, ich bin orientierungslos!"
            http://wwwtech.de/