new_prototyper: Neue Methode für Date-Object - ist das gutes scripting?

Hallo liebe Leute,
fange gerade an, mich für das Aufbauen einer eigenen kleinen library zu begeistern.
U.a. möchte ich dem Date-Objekt eine neue Methode zuweisen, da ich aber in Sachen
Prototyping noch unerfahren bin, interessiert mich Eure Meinung, ob der Code gut
geschrieben ist, oder ob man den (viel) besser/sinnvoller schreiben kann:

  
// ein bestimmtes Array-Element löschen  
	Array.prototype.kill = function($) {  
		var m;  
		for (m=0;m<this.length;m++) {  
			if (m >= $) {  
				this[m] = this[m + 1];  
			}  
		}  
		this.length = this.length-1;  
	};  
  
// date = gewünschte Datums-Form als String; lang = Sprache  
// Beispiele: yyyy:2011, d:1, hh:17, wd:Dienstag, month:November  
// Beispiele für erlaubte Punktuation: , . ; - / :  
// Sprachen: deu=deutsch, eng=english, esp=espanol  
    Date.prototype.toLocalDate = function(date,lang) {  
        var i,  
            results = [],  
            year = this.getYear(),  
            Year = this.getFullYear(),  
            month = this.getMonth() + 1,  
            day = this.getDate(),  
            weekDay = this.getDay(),  
            hour = this.getHours(),  
            minute = this.getMinutes(),  
            second = this.getSeconds(),  
            wochentage = ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],  
            weekdays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],  
			diasdelasemana = ["Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado"],  
            monate = ["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],  
            months = ["January","February","March","April","May","June","July","August","Septembre","Octobre","Novembre","Decembre"],  
			meses = ["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],  
  
            val = date,  
            search1 = /\W/g,  
            search2 = /\w*/gi,  
            punc = val.match(search1),  
            settings = val.match(search2);  
            settings.length = settings.length - 1;  
  
        for (i = 0; i<settings.length; i++) {  
            if (settings[i] != "" && settings[i] != ",") {  
                results.push(evaluateSetting(settings[i]));  
            } else { results.push(punc[0]); punc.kill(0); }  
        }  
  
        function evaluateSetting(val) {  
             switch (val) {  
                case "yyyy"   : return Year; break;  
                case "yy"     : return year; break;  
                case "mm"     : return fix(month); break;  
                case "m"      : return month; break;  
                case "month"  : if (lang == "deu") { return monate[month]; }  
								else if (lang == "eng") { return months[month]; }  
								else if (lang == "esp") { return meses[month]; } break;  
                case "dd"     : return fix(day); break;  
                case "d"      : return day; break;  
                case "wd"     : if (lang == "deu") { return wochentage[weekDay]; }  
								else if (lang == "eng") { return weekdays[weekDay]; }  
								else if (lang == "esp") { return diasdelasemana[weekDay]; } break;  
                case "hh"     : return fix(hour); break;  
                case "h"      : return hour; break;  
                case "minmin" : return fix(minute); break;  
                case "min"    : return minute; break;  
                case "ss"     : return fix(second); break;  
                case "s"      : return second; break;  
                default       : return false;  
            }  
        };  
  
        function fix(val) {  
            if (val.toString().length == 1) {  
                val = "0" + val;  
            }  
            return val;  
        };  
  
        var localDate = results.join('');  
        return localDate;  
    };  
  
// Beispiel:  
var datum = new Date();  
alert(datum.toLocalDate('wd, d. month yyyy, hh:minmin','esp'));  
// ergibt z.B.: Martes, 1. Noviembre 2011, 17:41  

Vielen Dank!!

  1. Hi,

    U.a. möchte ich dem Date-Objekt eine neue Methode zuweisen, da ich aber in Sachen Prototyping noch unerfahren bin, interessiert mich Eure Meinung, ob der Code gut geschrieben ist, oder ob man den (viel) besser/sinnvoller schreiben kann:

    Schon die Frage im Titel lässt sich mit „Nein“ beantworten – unabhängig vom konkreten Code.

    Maintainable JavaScript: Don’t modify objects you don’t own
    What’s wrong with extending the DOM

    Letzteres bezieht sich zwar konkreter auf das Erweitern von DOM-Objekten – aber ein Großteil der Argumente gilt auch für die restlichen nativen JS-Objekte.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Hi Chris,

      Schon die Frage im Titel lässt sich mit „Nein“ beantworten – unabhängig vom konkreten Code.

      Danke, für die Links! Hab ich jetzt als Lesezeichen und werd ich mir bei Gelegenheit durchlesen.
      Auch, wenn das direkte Erweitern von js-hauseigenen Objekten problematisch ist,
      so würde ich doch gerne wissen, ob mein Code gut/"sauber" ist - wenn mich die Seiten, auf die Du referierst, überzeugen, dann werde ich eben eigene Objekte basteln, die dasselbe leisten.

      Lieben Gruß*

    2. Schon die Frage im Titel lässt sich mit „Nein“ beantworten – unabhängig vom konkreten Code.

      Das ist undifferenziert.

      Maintainable JavaScript: Don’t modify objects you don’t own
      What’s wrong with extending the DOM

      Kontrastiere bitte
      Extending built-in native objects. Evil or not? ebenfalls von kangax

      Das sieht die Lage schon anders aus. (Dort geht es allerdings um ES5-Shims, nicht um willkürliche Eigenerfindungen.)

      Mathias

      1. Hallo nochmal,

        Extending built-in native objects. Evil or not? ebenfalls von kangax

        Das sieht die Lage schon anders aus. (Dort geht es allerdings um ES5-Shims, nicht um willkürliche Eigenerfindungen.)

        Habe die Seite überflogen. Ich werde also meine "willkürliche Eigenerfindung" als Methode eines eigenen Objektes einführen. Für viele meiner Zwecke ist diese Methode sinnvoll (zumindest erscheint sie mir als solches) und darum formulier ich die Frage etwas um:
        Angenommen, ich hätte die Methode nicht einem built-in-object zugewiesen - erkennt irgendjemand einen Fauxpas oder generell schlechte Herangehensweisen (abgesehen davon, dass ich direkt dem Date-Objekt eine neue Methode verpasst habe).

        Vielen Dank nochmal

      2. Hi,

        Kontrastiere bitte
        Extending built-in native objects. Evil or not? ebenfalls von kangax

        Das sieht die Lage schon anders aus. (Dort geht es allerdings um ES5-Shims, nicht um willkürliche Eigenerfindungen.)

        Das ist aber der wesentliche Punkt.
        Dort geht es nur darum, definierte Funktionalität nachzurüsten, wenn sie nicht nativ vorhanden sein sollte.
        Dass das Kollisions-Argument dabei nicht zieht, ist klar.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
  2. Hallo,

    fange gerade an, mich für das Aufbauen einer eigenen kleinen library zu begeistern.
    U.a. möchte ich dem Date-Objekt eine neue Methode zuweisen, da ich aber in Sachen
    Prototyping noch unerfahren bin, interessiert mich Eure Meinung, ob der Code gut
    geschrieben ist, oder ob man den (viel) besser/sinnvoller schreiben kann:

    Das Erweitern der Prototypen der Host-Objekte birgt vor allem generelle Probleme. Man belegt einen Namen, der in einigen Browsern in Zukunft belegt sein könnte, weil sich die Sprache weiterentwickelt. Auch andere JavaScripte können den Namen belegen, die Implementation kann jedoch abweichen. Daher hat man sich darauf geeinigt, wiederverwendbare und zukunftsfähige Scripte zu kapseln, sodass sie möglichst wenig Spuren an den bestehenden, geteilten Objekten hinterlassen. Von dieser Faustregel kann man natürlich in einigen Fällen abweichen. Datumsformatierung ist ein Fall, den man m.M.n. auch ohne Erweiterung des Date-Prototyps komfortabel umsetzen kann.

    // ein bestimmtes Array-Element löschen
    Array.prototype.kill = function($) {

    Welchen Zweck erfüllt diese Methode? http://de.selfhtml.org/javascript/objekte/array.htm#splice@title=splice(index, 1) sowie http://de.selfhtml.org/javascript/objekte/array.htm#shift@title=shift und http://de.selfhtml.org/javascript/objekte/array.htm#pop@title=pop existieren.

    Mathias

    1. Hey Mathias,
      vielen Dank für Deine Antwort :)

      [zu kill: fand das wunderbar intuitiv und kurz - aber hast Recht, splice existiert]

      lieben Gruß

  3. nur so nebenbei:
    dir ist der Fehler hier

    month = this.getMonth() + 1,

    monate = ["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],

    case "month"  : if (lang == "deu") { return monate[month]; }

      
    nicht aufgefallen?
    
  4. Hi,

    wochentage = ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],
                weekdays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
    diasdelasemana = ["Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado"],

    case "wd"     : if (lang == "deu") { return wochentage[weekDay]; }
                    else if (lang == "eng") { return weekdays[weekDay]; }
                    else if (lang == "esp") { return diasdelasemana[weekDay]; } break;

      
    Wie wäre es, die übersetzten String anders abzuspeichern? Ein erster Ansatz wäre etwas wie  
      
    ~~~javascript
      
    var weekday_names = {  
      'deu' : ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],  
      'eng' : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],  
      'esp' : ["Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado"]  
    };  
      
    Dann kannst du einfach mit [code lang=javascript]weekday_names[lang][weekDay]
    ~~~ zugreifen und brauchst kein umständliches if/else-Gedöns mehr, um das auseinanderzuhalten (was dir enorme Vorteile bringt, wenn du eine zusätzliche Sprache einfügen willst).  
      
    Und als nächstes könntest du die Datenhaltung nochmals umstellen, z.B.:  
    ~~~javascript
      
    var i18n_strings = {  
      'deu' : {  
        'weekday_names' : [ /* ... */ ],  
        'month_names' : [ /* ... */ ]  
      },  
      'eng' : { /* .... */ }  
    };  
    
    

    Dann suchst du am Anfang deines Codes die Sprache aus und speicherst diese zwischen.

      
      
    var mylang_strings = i18n_strings['deu'];
    

    Im Folgenden brauchst du nur noch auf mylang_strings zugreifen und brauchst keinerlei Fallunterscheidung mehr. Du könntest sogar die Daten in eine externe Datei auslagern.

    deutsch.js könnte dann so aussehen:

      
    var i18n_strings = i18n_strings || {};  
    i18n_strings['deu'] = {  
        'weekday_names' : [ /* ... */ ],  
        'month_names' : [ /* ... */ ]  
      }  
    
    

    Von solchen Sprachdateien kannst du beliebig viele einbinden und kannst dann auf die Sprachen zugreifen. Um eine Sprache mehr anzubieten, einfach Sprachdatei erstellen und dann einbinden.

    Bis die Tage,
    Matti

    1. @@Matti Mäkitalo:

      nuqneH

      (Almost) Full ACK. Nur als Sprachkennzeichnungen würde ich ausschließlch die nach BCP 47 verwenden (de, en, es). [qa-lang-2or3]

      Qapla'

      --
      Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
      (Mark Twain)
      1. Hi,

        (Almost) Full ACK. Nur als Sprachkennzeichnungen würde ich ausschließlch die nach BCP 47 verwenden (de, en, es). [qa-lang-2or3]

        hehe, ich habe daran gedacht, dazu etwas zu schreiben. Aber da hat einfach die Faulheit bei mir gesiegt :)

        Bis die Tage,
        Matti

    2. var weekday_names = {
        'deu' : ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],
        'eng' : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
        'esp' : ["Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado"]
      };

      Stilkritik:

      • JavaScript ist camelCaseLand
      • Object-Literal: Die Anführungszeichen um die Keys 'deu', 'eng', 'esp' sind in diesen Fällen nicht nötig
      • Vielleicht würde man der Lesbarkeit halber 'Sonntag Montag Dienstag ...'.split(' ') schreiben
      I18n.weekdayNames = {  
        de: 'Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag'.split(' '),  
        ...  
      };
      

      var mylang_strings = i18n_strings['deu'];[/code]
      i18n_strings['deu'] = {

      -  In JavaScript gibt es keinen Unterschied zwischen Hashes und Objekten wie in anderen Sprachen. Die Bracket-Schreibweise zum Zugriff auf die Eigenschaft ist unnötig, wenn darin nur ein String-Literal steht, die Standard-Dot-Schreibweise i18n_strings.deu reicht.

      Ansonsten ist die Vorschlag, die Aufgaben zu trennen und die Locales gesondert und lose gekoppelt abzuspeichern, sehr gut. So arbeiten auch größere I18n-Systeme in JavaScript.

      Mathias

      1. Hi,

        Stilkritik: [...]

        vielen Dank. Das meiste entsteht daraus, dass ich den gleichen Stil auch in anderen Sprachen nutze (C++/PHP/Perl/...) und mich dann nicht umstelle(n muss). Aus reiner JavaScript-Sicht hast du vollkommen recht.

        Bis die Tage,
        Matti

      2. Hi,

        Stilkritik:

        • Object-Literal: Die Anführungszeichen um die Keys 'deu', 'eng', 'esp' sind in diesen Fällen nicht nötig

        Ich finde es ist guter Stil wenn Objekte in JSON-schreibweise erstellt werden das Ganze auch valide zu machen.

        {foo:1} ist nicht valide, {'foo':1} schon.

        ~dave

          • Object-Literal: Die Anführungszeichen um die Keys 'deu', 'eng', 'esp' sind in diesen Fällen nicht nötig

          Ich finde es ist guter Stil wenn Objekte in JSON-schreibweise erstellt werden das Ganze auch valide zu machen.

          JavaScript ist nicht JSON; JSON ist eine Untermenge von JavaScript - wieso sollte man sämtliche Object-Literale in JavaScript JSON-konform schreiben? JavaScript lässt viel mehr zu, und das ist auch gut so.
          Man kann natürlich argumentieren, dass man das Object-Literal irgendwann mal als JSON übertragen und verarbeiten will. Dann wäre eine Kompatibilität hilfreich. Dann dürfte man aber auch weitere Vereinfachungen nicht nutzen (wie z.B. 'str1 str2'.split(' ')) und müsste sich streng auf in JSON mögliche Strukturen beschränken. Das halte ich allgemein nicht für sinnvoll. Wenn man JSON braucht, kann man den entstandenen Object-Literal immer noch entsprechend serialisieren – das ist ja ohne Aufwand möglich.

          Mathias

      3. Hi,

        • Vielleicht würde man der Lesbarkeit halber 'Sonntag Montag Dienstag ...'.split(' ') schreiben

        Es mögen Sprachen existieren, in denen Wochentage nicht nur aus einem Wort bestehen(?).
        Für die dann wieder eine Extrawurst machen? Da tendiere ich doch eher dazu, gleich bei der „eindeutigen“ Notation zu bleiben.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Es mögen Sprachen existieren, in denen Wochentage nicht nur aus einem Wort bestehen(?).
          Für die dann wieder eine Extrawurst machen? Da tendiere ich doch eher dazu, gleich bei der „eindeutigen“ Notation zu bleiben.

          Eine Extrawurst ist es nicht. Es geht ja nur um eine Vereinfachung der Schreibweise, keine Muss-Regel. Wo nötig, kann man ['…', '…', '…', …] schreiben, wo möglich, kann man sich der Lesbarkeit und der Kürze des Codes für halber '… …'.split(' ') entscheiden – genau wie beispielsweise in Ruby bei %w() und Perl bei qw(). Falls Abweichler auftreten, kann man sich aus Gründen der Einheitlichkeit durchgehend für die klassische Array-Notation entscheiden.

          Mathias

        2. @@ChrisB:

          nuqneH

          • Vielleicht würde man der Lesbarkeit halber 'Sonntag Montag Dienstag ...'.split(' ') schreiben

          Es mögen Sprachen existieren, in denen Wochentage nicht nur aus einem Wort bestehen(?).

          Es ließe sich ein geeigneteres Zeichen als Separator finden:
          'Sonntag;Montag;Dienstag;...'.split(';')

          Aber ich würde auch eher das Splitten selbst tun und nicht JavaScript überlassen.

          Qapla'

          --
          Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
          (Mark Twain)
      4. [latex]Mae  govannen![/latex]

        • Vielleicht würde man der Lesbarkeit halber 'Sonntag Montag Dienstag ...'.split(' ') schreiben

        I18n.weekdayNames = {

        de: 'Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag'.split(' '),
          ...
        };

          
        Wenn der Methodenaufruf im Literal steht, kann er meines Erachtens schnell übersehen werden, daher ist "Lesbarer" sicherlich relativ.  
          
        Ich bin der Meinung, daß ein reines Daten-Objekt in Literal-Notation auch ausschließlich Daten enthalten sollte. Klar, man spart sich bei deiner Schreibweise viele Zeichenketten-Begrenzer und Trenn-Komma.  
          
        Wenn es wirklich nur um die Lesbarkeit geht, dann kann man die Daten auch gleich zeilenweise notieren  
          
        ~~~javascript
        I18n.weekdayNames = {  
          de: [  
              "Sonntag",  
              "Montag",  
              "Dienstag",  
              "Mittwoch",  
              "Donnerstag",  
              "Freitag",  
              "Samstag"  
          ],  
          en: [  
              "Sunday",  
              "Monday",  
              "Tuesday"  
              ...  
          ]  
        };
        

        Die zusätzlichen Zeichen werden bei der Auslieferung ohnehin weg-komprimiert.

        Es ist eine Frage der persönlichen Präferenzen und des spezifischen Aufbaus des Objekts; glücklicherweise ist Javascript das gleich. ;)

        Stur lächeln und winken, Männer!
        Kai

        --
        Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
        in Richtung "Mess up the Web".(suit)
        SelfHTML-Forum-Stylesheet
  5. Hallo nochmal an alle,

    vielen, vielen Dank an die reichliche/n und hilfreiche/n Kritik/Verbesserungsvorschläge!!!

    Leider bin ich erst jetzt wieder an den Rechner gekommen und konntedaher vorher noch nicht bedanken.

    Bin wieder (wie fast immer, wenn ich hier etwas poste) um einiges schlauer geworden :)

    Ganz lieben Gruß