MB: eigenen pseudo Datentyp definieren

moin Community,

Kann man in Frameworks, die wiederkehrender Datenstruktueren in sequenzieller Abfolge, in pseudo Datentypen definieren? Ich beziehe mich auf eine fast gleiche Frage Datentypen Intertface

new Database( new TyeDatabase( 'mysql:host=localhost;dbname=mydatabse', 'root', '' ) );
new URLRouter( new TypeURLRouter( 'en', 'default', 'home', 'index', '1' ) );

macht man das bei striktem, objektorientierten PHP so? Ich tu mich sehr schwer wenn ich angeforderte primitive datentypen in einer habe die in ihrer Reihenfolge fest definierte sind. Warum man da kein Custom Datentype kreiert, die man in allmöglichen Bereichen im System einsetzt, ist sehr suspekt.

Außerdem könnte man bei URLRouter Rückgabewerten nicht alle erdenklichen GET-Parameter holen getLanguage(), getController(), getPrefix(), getMethod(), getParams(), sondern in einen Rutsch definierten Typ...

return new TypeURLRouter( $language, $prefix, $method, $params )

vlg MB

  1. Tach!

    Kann man in Frameworks, die wiederkehrender Datenstruktueren in sequenzieller Abfolge, in pseudo Datentypen definieren?

    Ich verstehe die Fragestellung nicht. Liegt einerseits an der Grammatik, andererseits weil sich mir aus den Begrifflichkeiten, in der Form wie sie zusammengebracht sind, nicht erschließt, was dein Problem ist.

    Generell kann ich sagen, dass man ganz hervorragend Datentypen unter Verwendung von Klassen und deren Eigenschaften definieren kann. Dafür sind sie ja da, dass man Daten, die eine Einheit bilden, zu einem Gebilde zusammenfasst.

    Ich tu mich sehr schwer wenn ich angeforderte primitive datentypen in einer habe die in ihrer Reihenfolge fest definierte sind.

    Daten, die in ihrer Reihenfolge fest definiert sind, kann man mit ein Array mit numerischm Index abbilden. Aber ich vermute mal, dass es dir gar nicht so sehr auf diese Reihenfolge ankommt, sondern darauf, dass du weißt, was die einzelnen Werte bedeuten. Dazu kann man Namen nehmen, zum Beispiel die von Objekteigenschaften oder zur Not assoziative Array-Keys.

    Warum man da kein Custom Datentype kreiert, die man in allmöglichen Bereichen im System einsetzt, ist sehr suspekt.

    Wenn du sowas wie ein Dictionary meinst, dann ist das assiziative Array sozusagen das PHP-Pendant dazu.

    Außerdem könnte man bei URLRouter Rückgabewerten nicht alle erdenklichen GET-Parameter holen getLanguage(), getController(), getPrefix(), getMethod(), getParams(), sondern in einen Rutsch definierten Typ...

    An einem assoziativen Array ist auch bei objektorientierter Arbeitsweise kein Makel, wenn man nicht vorhersehbare Schlüssel-Wert-Paare in einer Struktur ablegen möchte.

    dedlfix.

    1. moin dedlfix,

      Kann man in Frameworks, die wiederkehrender Datenstruktueren in sequenzieller Abfolge, in pseudo Datentypen definieren?

      Ich verstehe die Fragestellung nicht. Liegt einerseits an der Grammatik, andererseits weil sich mir aus den Begrifflichkeiten, in der Form wie sie zusammengebracht sind, nicht erschließt, was dein Problem ist.

      Sorry. Da ich weis, dass ich im Ausdruck probleme habe, habe ich zur Frage direkt danach ein Besipiel angeführ: die geforderten Parameter zur Instanziiereung eines PDO-Objekts. Das ist mit "wiederkehrender Datenstruktueren in sequenzieller Abfolge" gemeint. Jedoch hast du meine Frage verstanden.

      Generell kann ich sagen, dass man ganz hervorragend Datentypen unter Verwendung von Klassen und deren Eigenschaften definieren kann. Dafür sind sie ja da, dass man Daten, die eine Einheit bilden, zu einem Gebilde zusammenfasst.

      Ok, kannst du mir n beipsiel geben? Ich kann mir überhauptnix drunter vorstellen? [ 'foo', 'bar' ], o in etwa?

      Aber ich vermute mal, dass es dir gar nicht so sehr auf diese Reihenfolge ankommt, sondern darauf, dass du weißt, was die einzelnen Werte bedeuten.

      Ja z.B. TypeURLRoute forder bei mir 4 mal Strings und am ende ein numerisches Array

      Dazu kann man Namen nehmen, zum Beispiel die von Objekteigenschaften oder zur Not assoziative Array-Keys.

      z.B.? Sorry, ich kann mir darunter nix vorstellen.

      Wenn du sowas wie ein Dictionary meinst, dann ist das assiziative Array sozusagen das PHP-Pendant dazu.

      Was ist in diesem Kontext ein Dictionary?

      vlg MB

      1. Tach!

        Generell kann ich sagen, dass man ganz hervorragend Datentypen unter Verwendung von Klassen und deren Eigenschaften definieren kann. Dafür sind sie ja da, dass man Daten, die eine Einheit bilden, zu einem Gebilde zusammenfasst.

        Ok, kannst du mir n beipsiel geben? Ich kann mir überhauptnix drunter vorstellen? [ 'foo', 'bar' ], o in etwa?

        Nun, vielleicht denkst du nur zu kompliziert. Wenn die Datenbank-Klasse Zugangsdaten braucht, dann könntest du folgende Klasse erstellen:

        class PdoServerDetails {
          public $dsn;
          public $username;
          public $password;
        }
        

        Fertig ist der Datentyp. Die Frage ist aber, ob sich das lohnt oder ob man nicht die drei Strings als Einzelwerte übergibt. In der Form hat das ja kaum Nutzen und nur etwas mehr Aufwand. Man könnte das jedoch sinnvoll erweitern, indem man von dieser Klasse den DSN-String aus gegebenen Einzelwerte zusammenbauen lässt.

        Dazu kann man Namen nehmen, zum Beispiel die von Objekteigenschaften oder zur Not assoziative Array-Keys.

        z.B.? Sorry, ich kann mir darunter nix vorstellen.

        Es ist im Prinzip nur eine Geschmackssache, ob du eine Klasse wie oben erstellst, und eine Instanz davon übergeben haben möchtest, oder ob du stattdessen ein assoziatives Array nimmst, dass die Eigenschaften als Keys haben muss.

        $pdoServerData = [
          'dsn' => ...,
          'username' => ...,
          'password' => ...
        ];
        

        Wenn du sowas wie ein Dictionary meinst, dann ist das assoziative Array sozusagen das PHP-Pendant dazu.

        Was ist in diesem Kontext ein Dictionary?

        Ein Dictionary ist das, was man anderswo nehmen muss, wenn man kein assoziatives Array zur Verfügung hat. Oder anders ausgedrückt, eine Verwaltungseinheit für Key-Value-Paare.

        dedlfix.

        1. moin dedlfix,

          besten dank für die Info :).

          vlg MB

          1. Tach!

            Noch ein Nachtrag zur Entscheidungshilfe assoziatives Array oder Klasse:

            Ein assoziatives Array (oder auch ein Dictionary) ist eine lose Sammlung von Key-Value-Paaren ohne konkrete Vorgaben. Da kann man alles reinstopfen unter jedem beliebigen (syntaktisch gültigem) Key. So eine Datenstruktur eigent sich in den Fällen, wenn man nicht weiß, was einen erwartet. Zum Beispiel sind die Querystring- oder Post-Parameter nicht genau definiert. Du wünschst dir zwar bestimmte Werte, aber was der Client letzlich sendet, ist seine Angelegenheit. Deshalb ist ein Array eine guter Container, der erstmal alles aufnimmt und du suchst dir raus, was du brauchst.

            In anderen Situationen ist jedoch genau festgelegt, was erwartet wird und der Aufrufer hat keine andere Wahl, als das zu übergeben, weil es sonst einen Syntax- oder anderen Fehler gibt. Das betrifft zum Beispiel die Daten, die eine DB-Klasse braucht, um eine Verbindung zum DBMS aufzubauen. Die können konkret benannt werden und somit steht auch ihre Anzahl fest. Dafür eignet sich eine Klasse mit genau definierten Eigenschaften besser als ein undefiniertes Array. Oder unter Verzicht des Umweges lässt man sich diese Werte eben als Funktionsparameter übergeben.

            Das Argument, man könne das übergebene Array mit einem Defaultwerte-Array mergen, ist nicht ganz von der Hand zu weisen. Aber dabei hat man die Nachteile des Arrays mit seinen beliebigen Key-Namen. In den Alternativen stehen die Namen ja fest, und dann kann auch eine IDE oder ein guter Editor mit Sprachenkenntnis behilflich sein beim Aufrufen von Funktionen oder beim Erstellen der Objekte. Der weiß dann ja, welche Parameter oder Eingenschafte existieren, beim Array jedoch nicht. Beim Array musst du selbst darauf achten, die Namen der Keys zu kennen und sie korrekt zu schreiben. Die Sache mit den Default-Werten lässt sich auch einfach lösen:

            function __construct($host, $username, $password, $port = 3306, $encoding = 'utf8') { ... }
            

            dedlfix.

        2. Nun, vielleicht denkst du nur zu kompliziert. Wenn die Datenbank-Klasse Zugangsdaten braucht, dann könntest du folgende Klasse erstellen:

          class PdoServerDetails {
            public $dsn;
            public $username;
            public $password;
          }
          

          Fertig ist der Datentyp. Die Frage ist aber, ob sich das lohnt oder ob man nicht die drei Strings als Einzelwerte übergibt.

          So ähnlich hätte ich es auch gemacht, wenn man will, kann man das zu einem Builder ausgbauen:

          class PdoBuilder
          {
              private $dsn;
              private $username;
              private $password;
              private $options = array();
          
              public function withDsn (string $dsn) : PdoBuilder {
                  $this->dsn = $dsn;
                  return $this;
              }
          
              public function withUsername (string $username) : PdoBuilder {
                  $this->username = $username;
                  return $this;
              }
          
              public function withPassword (string $password) : PdoBuilder {
                  $this->password = $password;
                  return $this;
              }
          
              public function withOptions (array $options) : PdoBuilder {
                  $this->options = $options;
                  return $this;
              }
          
              public function create () : PDO {
                  if (empty($this->dsn)) {
                      throw new Exception('Missing DSN. Consider calling the `withDsn`-method on this builder before invoking the `create`-method.');
                  }
                  return new PDO (
                      $this->dsn,
                      $this->username,
                      $this->password
                      $this->options
                  );
              }
          }
          

          Der Nachteil ist ganz klar die Wortfülle der Implementierung. Der Vorteil ist die einfache Handhabung für den Nutzer.

          $pdo = (new PdoBuilder())
              ->withUsername($username)
              ->withPassword($password)
              ->withDsn($dsn)
              ->withOptions($options)
              ->create();
          

          Man hat nicht das Problem von assoziativen Arrays, dass sich Typos bei der Erzeugung einschleichen können. Gleichzeitig spielt die Reihenfolge in denen man die Paramter übergibt aber auch keine Rolle. Außerdem sind dadurch die Erzeugung und Nutzung der Obejkte klar voneinander getrennt. Man muss die öffentliche Schnittstelle der zu erzeugenden Klasse nicht anfassen. Der Ansatz eignet sich also insbesondere dann, wenn man mit fremden Klassen arbeitet oder wenn man seine Schnittstelle nicht ändern will, weil man dadurch eine inkonsistente API oder eine Abwärtsinkompatibilität erzeugen würde.

          1. Noch einfacher ist es, wenn lediglich ein einziger Aliasname zu übergeben ist. Der PDOBuilder findet anhand dieses Alias sämtliche Zugangsdaten (host, port, dbname, user, pass) in einer Konfigurationsdatei und zwar pronto.

            1. Tach!

              Noch einfacher ist es, wenn lediglich ein einziger Aliasname zu übergeben ist. Der PDPBuilder findet anhand dieses Alias sämtliche Zugangsdaten (host, port, dbname, user, pass) in einer Konfigurationsdatei und zwar pronto.

              Dann wäre es kein universeller PDOBuilder mehr, der unabhängig von der tatsächlichen Datenquelle arbeitet, sondern ein spezieller Konfigurationsdatenbesorger, der nur mit genau einer Sorte von Quelle arbeiten kann. Zu dem würde dann auch nicht mehr der Name passen.

              dedlfix.

              1. Dann wäre es kein universeller PDOBuilder mehr

                Ooch der kann schon so bleiben, nur, ich würde einen Wrapper drüber setzen.

                Freundschaft 😉

          2. Tach!

            Der Nachteil ist ganz klar die Wortfülle der Implementierung. Der Vorteil ist die einfache Handhabung für den Nutzer.

            $pdo = (new PdoBuilder())
                ->withUsername($username)
                ->withPassword($password)
                ->withDsn($dsn)
                ->withOptions($options)
                ->create();
            

            Du machst das natürlich gleich wieder in ganz hübsch. Das ist in der Tat eine sehr einfache Handhabung, besonders dann, wenn man Autovervollständigung (mit CamelHumps) hat. Ohne diese wäre es auch noch recht viel Tipparbeit im Verhältnis zu einfachen Funktionsparametern. Für meine eigenen Kreationen hab ich sowas noch nicht aufgesetzt, weil es für mich persönlich aufwendiger und meist weniger von Nutzen ist. Für ein Framework, dass sich womöglich an eine breite Masse wendet, mag die Kosten-Nutzen-Rechnung wieder ganz anders aussehen.

            Ein Nachteil ist mir aber grad noch eingefallen. Fehlende Pflichtparameter merkt man erst zur Laufzeit, wenn sich die create()-Methode beschwert.

            dedlfix.

          3. Man hat nicht das Problem von assoziativen Arrays, dass sich Typos bei der Erzeugung einschleichen können.

            Dafür gibt es Lösungen. Und es ist gerade die Zweckbestimmung assoziativer Arrays bzw. abstrakter Datentypen, Daten die zusammenghören auch zusammengehörig zu transportieren. Gerade das erleichtert ja auch Debugging, Fehlersuche und letztendlich Qualitätssicherung.

            Du hingegen zerreißt zusammengehörige Daten, Daten die funktional zusammengehören weil sie einzeln keinen Sinn ergeben. Datenkonsistenz ist dadurch nicht mehr gewährleistet. All diese Probleme lassen sich vermeiden mit entschieden weniger Programmieraufwand gegnüber Deinem Konstrukt.

            MfG

  2. Hallo MB,

    man definiert normalerweise dann eigene Datentypen, wenn die verwendeten Daten tatsächlich zusammengehören und als diese Einheit auch verwendet werden. In dem Fall erstellst Du eine Klasse und der Frameworknutzer verwendet sie.

    Einen Typ (eine Klasse) zu definieren, um die Parameter für einen Konstruktor zu einem zu bündeln, macht IMO wenig Sinn. Da hilft Dir normalerweise deine IDE und die eingebrachten PHPDOC Kommentare dabei weiter, die Parameter in der richtigen Reihenfolge zu übergeben. Benannte Argumente existieren in PHP nach wie vor nur als RFC, insofern kannst Du deinen Nutzern keine freie Reihenfolge bei der Argumentübergabe anbieten (d.h. du kannst schon, mit assoziativen Arrays, das ist aber arg fragil).

    Es kann SCHON Sinn machen, einen Konstruktor so aufzubauen, dass er Objekte als Parameter erwartet. Das macht man dann aber eher wegen der Funktionalität dieser Objekte und nennt es Dependency Injection, d.h. Du lieferst einer Klasse Bausteine mit, die sie für ihre Funktion verwenden soll und die ein bestimmtes Interface implementieren. Zum Beispiel einen Database-Accessor, der wahlweise PDO, Oracle oder MongoDB anspricht. Oder einen Logger, der wahlweise alles raushaut oder alles wegschmeißt.

    Rolf

    --
    Dosen sind silbern
  3. Namentliche Parameter in einem asoziativen Array einer Funktion zu übergeben ist deswegen interessant, weil erstens die Reihenfolge keine Rolle mehr spielt, zweitens Defaults gesetzt werden können und drittens der Code damit übersichtlicher wird. D.h. Du übergibst ein Array mit Schlüssel-Werte-Paaren, hast ein Array mit demselben Aufbau als Default in deiner Methode oder einem Konstruktor und machst nach der Übergabe ein $config = array_merge($default, $parameter);

    Beispiel:

    class MySQL{
        protected $EE;   // for PDOException
        protected $DBH;
        public function __construct($cfg = array()){
            try{
                $this->dbh($cfg);
            }
            catch(PDOException $e){
                $this->EE = $e->getMessage();
            }
        }
    
        private function dbh(&$cfg = array()){
            $default = array(
                'user' => '',
                'pass' => '',
                'host' => 'localhost',
                'port' => 3306,
                'base' => '',
            );
            $cred = array_merge($default, $cfg);
            $this->DBH = new PDO(sprintf("mysql:dbname=%s;host=%s", $cred['base'], $cred['host']),
                $cred['user'], $cred['pass'],
                array(
                    PDO::ATTR_TIMEOUT => 2,
                ));
            $this->DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
    
        // Exception Error ausgeben
        public function ee(){
            if($this->EE){ return $this->EE; }
            else{ return; }
        }
    }
    
    $m = new MySQL( array( 'host' => 'otto'  )  );
    
    print_r($m);
    

    In Perl seit Jahrzehnten bewährt übrigens..

    1. Hallo pl,

      du hast insofern Recht, dass die Reihenfolgeneutralität der Parameter eine gute Sache ist. Es gibt ja auch genug Libraries, die das nutzen und einen Konfigurationsbaum als Parameter erwarten. Und diese Libraries nutzen gerne - wie auch dein Beispiel - Merge-Mechanismen, um den übergebenen Baum mit einem Defaults-Baum zu mischen. Alles schick und flott.

      Andererseits sehe ich das ohne passendes Tooling (wie es z.B. C# bei Objekt-Initializern bringt) zwiespältig… Eine Library wird zur Laufzeit eher nicht prüfen, ob der Objektbaum falsche Äste eingepfropft bekommen hat. Wie lange brauchst Du, um den folgenden Fehler zu sehen? Hier ist es einfach, in einem komplexeren Config-Baum nicht so.

      $newCfg = [ 'user' => '',
                  'pass' => '',
                  'host' => 'localhost',
                  'pont' => 3306,
                  'base' => '',
                ];
      

      Rolf

      --
      Dosen sind silbern
      1. Den eingebauten Fehler sehe ich schon aber das eigentliche Problem ist ein ganz Anderes: Es sind die Default-Werte -> schwubbs landest Du auf der falschen Kiste und wunderst Dich, dass die Datenbank nicht da ist. Das ist ein systematischer Fehler der nicht so schnell gefunden wird, eben weil er systematisch begangen wird. Tippfehler hingegen werden schneller gefunden weil sie nicht systematisch sind.

        Andererseits erhöht ein solches struct die Lesbarkeit von Code enorm. Perl kommt einem solchen Syntax entgegen und erlaubt Barwords für die Schlüsselnamen. Und ganz gewissenhafte Entwickler bedienen sich dieser Schreibweise mit einem leading dash:

        MyClass->new( -file => 'foo', -lock => 1 );

        Faazit: Anstatt Defaults zu setzen, wird nur der Schlüssel notiert was der besseren Lesbarkeit dienlich ist. Parameter die erforderlich sind werden auf null (undef) gesetzt und das wirft eine Ex wenn der Parameter fehlt. MfG

        1. Hallo pl,

          Vorsicht, hier könnten Kinder mitlesen, die in einer Nacktbar nichts verloren haben (barword vs bareword 😂).

          Du willst aber nicht ernsthaft barewords als Best Practice verkaufen? Auch nicht mit dem Minus davor (das hoffentlich nicht als Teil eines sub-Namens erlaubt ist)? Warum wurden wohl die strict-Modi eingebaut, die dann Zeter und Mordio schreien?

          Abgesehen davon löst Du damit nicht das Problem, das Keys einen Tippfeh1er enthalten können.

          Und so langsam krieg ich hier die Krise - aus diesen Diskussionen lerne ich mehr über Perl als ich je wissen wollte.

          Rolf

          --
          Dosen sind silbern
          1. Du willst aber nicht ernsthaft barewords als Best Practice verkaufen?

            Urteile doch selbst was leserlicher ist {foo}{bar} oder {'foo'}{'bar'} oder gar ['foo']['bar'].

            Die Logik dahinter: Perl erwartet als Schlüssel in einem Hash grundsätzlich einen String. Von daher sind Stringbegrenzer überflüssig.

            Im Übrigen sind Perls barewords like -file aus der UNIX Welt entlehnt. D.h. die müssen sich da ja irgendwie bewährt haben 😉

            Und so langsam krieg ich hier die Krise - aus diesen Diskussionen lerne ich mehr über Perl als ich je wissen wollte.

            Das freut mich außerordentlich. Ansonsten kriegt meine Frau immer alles ab 😀

            Viele Grüße.

            PS: Auch in JS Objekten sind Stringbegrenzer für die Properties nicht erforderlich. Es sei denn, da will jemand reservierte Worte verwenden.

            1. Hallo pl,

              Und so langsam krieg ich hier die Krise - aus diesen Diskussionen lerne ich mehr über Perl als ich je wissen wollte.

              Das freut mich außerordentlich. Ansonsten kriegt meine Frau immer alles ab 😀

              Ich nenn' Dich aber jetzt nicht Schatz!

              PS: Auch in JS Objekten sind Stringbegrenzer für die Properties nicht erforderlich. Es sei denn, da will jemand reservierte Worte verwenden.

              In JS ist die irrtümliche Nennung eines Funktionsnamens aber auch nicht direkt ein Funktionsaufruf, bzw. wenn ich als Key in einem Objektliteral einen Variablennamen hinschreibe, löst es ihn nicht zum Wert auf. Das ist also schon ein Unterschied.

              Rolf

              --
              Mein Schatzzzzz!!!
              1. Hallo Rolf

                Auch in JS Objekten sind Stringbegrenzer für die Properties nicht erforderlich. Es sei denn, da will jemand reservierte Worte verwenden.

                Das war früher mal richtig, trifft aber schon lange nicht mehr zu. (Edit. Danke @Rolf B für die Erinnerung) Heutzutage gilt: Auch wenn es sich bei dem Namen einer Objekteigenschaft oder -methode um ein reserviertes Wort handelt, muss der Name nicht als String angegeben werden. Nicht bei der Definition der Eigenschaft oder Methode, und auch nicht bei ihrer Referenzierung.

                Sehen wir uns mal ein Beispiel an:

                const object = {
                
                  extends (source = {}) {
                    Object.assign(this, source);
                  }
                
                };
                
                
                object.extends({
                
                  default: 42,
                
                  function (value = this.default) {
                    console.log(value);
                  }
                
                });
                
                
                object.function(); // 42
                

                Hier werden zwei Objekte in Literalsyntax definiert. Das erste Objekt, welches der Konstante mit dem Bezeichner object zugewiesen wird, besitzt eine Methode namens extends. Bei diesem Namen handelt es sich um ein reserviertes Wort, genauer gesagt, um ein Schlüsselwort der Sprache. Das Keyword extends wird verwendet, um eine abgeleitete Klasse zu erzeugen:

                class Stack extends Array {
                
                  peek () {
                    return this[this.length - 1];
                  }
                
                }
                
                
                console.log(new Stack(1, 2, 3).peek()); // 3
                

                Obwohl es sich bei extends um ein reserviertes Wort handelt, muss es bei der Verwendung als Name einer Eigenschaft oder einer Methode in einem Objektliteral nicht als String notiert werden. Gleiches gilt für die Schlüsselworte default und function, die in dem Objekt verwendet werden, das der Methode extends bei ihrem Aufruf übergeben wird:

                object.extends({
                
                  default: 42,
                
                  function (value = this.default) {
                    console.log(value);
                  }
                
                });
                

                Wie hier beim Aufruf der Methode extends und der Definition des Standardwertes für den Parameter der Methode function zu sehen ist, muss in einem Elementausdruck der Name der referenzierten Eigenschaft oder Methode ebenfalls nicht als String angegeben werden, auch wenn es sich bei dem Namen um ein reserviertes Wort handelt.

                Die Definition für einen Identifier, also einen Bezeichner sieht in Backus-Naur-Form ausgedrückt etwa wiefolgt aus. Wobei zu beachten ist, dass die BNF keine Negation kennt, aber das ist an dieser Stelle auch nicht wichtig, schließlich wollen wir kein JS parsen, sondern nur die Syntax nachvollziehen.

                <identifier> ::= <identifier-name> not <reserved-word>
                

                Ein Bezeichner und sein Name stellen also zwei verschiedene Nichtterminalsymbole dar. Ein Bezeichner ist demnach einfach ein <identifier-name>, der kein reserviertes Wort ist. Die Syntax für ein Objektliteral würde dann vereinfacht und sehr unvollständig etwa so aussehen:

                <object-literal> ::=
                
                    { <optional-whitespace> } |
                
                    { <property-definition-list> }
                
                
                <property-definition-list> ::=
                
                    <property-definition> |
                
                    <property-definition-list> , <property-definition>
                
                
                <property-definition> ::=
                
                    <property-name> : <assignment-expression> |
                
                    <method-definition>
                
                
                <method-definition> ::=
                
                    <property-name> ( <formal-parameters> ) { <function-body> }
                
                
                <property-name> ::=
                
                    <literal-property-name> |
                
                    <computed-property-name>
                
                
                <literal-property-name> ::=
                
                    <identifier-name> |
                
                    <numeric-literal> |
                
                    <string-literal>
                

                Hier fehlen einige Ableitungsregeln und einige Produktionen sind unvollständig, nichtsdestotrotz kann man erkennen, dass bei der Notierung eines Eigenschafts- oder Methodennamens in Form eines Literals ein beliebiger <identifier-name> verwendet werden kann. Eine Einschränkung, wonach es sich bei diesem Namen nicht um ein reserviertes Wort handeln darf, gibt es hier grundsätzlich nicht.

                const object = {
                
                  typeof: 'object',
                
                  new () {
                    return Object.create(this);
                  }
                
                };
                
                
                console.log(object.new().typeof); // object
                

                Eine Konstruktion wie in dem Beispiel oben ist also ohne weiteres möglich. Daraus ist allerdings nicht abzuleiten, dass die Verwendung von reservierten Wörtern für Eigenschafts- und Methodennamen auch empfehlenswert ist. Hier ist immer abzuwägen, ob durch den Gebrauch des reservierten Wortes die Lesbarkeit des Codes eingeschränkt wird.

                Eine Objekteigenschaft default oder eine Methode do zu nennen muss je nach Kontext nicht zwingend schlecht sein. Bei den Keywords const oder function andererseits ist es schwer vorstellbar, dass bei deren Verwendung als Eigenschafts- oder Methodenname die Lesbarkeit nicht leidet. Hier ist also definitiv Vorsicht geboten und im Zweifel sollte auf diese Praxis verzichtet werden.

                wenn ich als Key in einem Objektliteral einen Variablennamen hinschreibe, löst es ihn nicht zum Wert auf

                Das kommt darauf an. Die von mir oben angegebene Produktion für Eigenschaftsdefinitionen war wie bereits angedeutet unvollständig. Tatsächlich müsste man das eher wiefolgt schreiben:

                <property-definition> ::=
                
                    <identifier-reference> |
                
                    <property-name> : <assignment-expression> |
                
                    <method-definition>
                
                
                <identifier-reference> ::= <identifier>
                

                Wenn in einem Objektliteral nur ein Bezeichner als Eigenschaft notiert wird, dann wird versucht, diese Referenz aufzulösen. Gelingt das, wird der Bezeichner als Eigenschaftsname und der mit dem Bezeichner assoziierte Wert als Eigenschaftswert verwendet. Kann die Referenz hingegen nicht aufgelöst werden, gibt das einen Reference Error.

                const number = 42;
                
                
                const object = {
                
                  number,
                
                  print () {
                    console.log(this.number);
                  }
                
                };
                
                
                object.print(); // 42
                

                In diesem Beispiel wird in dem Objektliteral als Eigenschaft der Bezeichner number notiert, ohne dabei einen Wert zuzuweisen. Da es hier in der lexikalischen Umgebung des Objektliterals eine Bindung für diesen Bezeichner gibt, wird wie beschrieben eine Eigenschaft mit dessen Namen angelegt, und dem Wert, mit dem hier die Konstante initialisiert wurde.

                Natürlich muss die Bindung für den Bezeichner nicht zwingend im selben Kontext existieren wie der Ausdruck mit dem das Objekt erzeugt wird. Es kann auch eine Konstante, Variable oder Funktion aus einem umgebenden Scope referenziert werden. Wichtig ist nur, dass die Referenz überhaupt aufgelöst werden kann. Und selbstverständlich folgendes:

                
                <property-definition> ::= <identifier-reference> ...
                
                
                <identifier-reference> ::= <identifier>
                
                
                <identifier> ::= <identifier-name> not <reserved-word>
                

                Da ein Bezeichner kein reserviertes Wort sein darf, kann eine Referenz auf einen Bezeichner zum Zwecke der Eigenschaftsdefinition natürlich auch kein reserviertes Wort enthalten.

                Viele Grüße,

                Orlok

              2. Das Problem was ich mir mit JS gemacht hatte, sah so aus:

                    var request = {
                        apply:   [device],
                        default: [$('#default'+device).text()],
                        times:   [$('#times'+device).text()]
                    };
                

                und die Lösung so:

                    var request = {
                        apply:   [device],
                        'default': [$('#default'+device).text()],
                        times:   [$('#times'+device).text()]
                    };
                

                Da gibts sogar einen Thead.

                1. Hallo pl,

                  ja, den Thread gibt's und ich habe deine Aussage dort vertrauensvoll als Erkenntnis mitgenommen.

                  Allerdings habe ich gerade in Chrome 60 und IE 11 versucht, Orloks Behauptung zu falsifizieren, und es ist mir nicht gelungen.

                  x = { apply: 1, default: 2 };
                  console.log(b.default)
                  

                  war ohne Probleme möglich. Also hat Orlok nicht grundsätzlich unrecht. Was man aber erwähnen muss: Es ist ein ECMAScript 5 Feature. Kangax (Obsolete Platforms einschalten) sagt, dass der IE8 es nicht beherrscht und ein paar Server-Engines (Rhino, DUK 1.x), die Masse der Desktop-Browser dagegen schon. D.h. ältere Smartphones könnten Probleme damit haben.

                  Rolf

                  --
                  Dosen sind silbern
                  1. Eine mögliche Chance zur Vermeidung reservierter Worte in eigenen Kontext besteht darin, der Syntaxhervorhebung des Editors zu vertrauen bzw. mehr Beachtung zu schenken 😉

                    Freundschaft.

      2. Noch einmal zu Tippfehlern, z.B. $DBH = DBClass->new( pont => 3306);

        Jetzt kommt es darauf an, ob für port ein Default konfiguriert ist oder nicht. Wenn ja, bleibt dieser vom Tippfehler unberührt. Das Problem dabei ist, dass hier in diesem Fall ein zufälliger Fehler zu einem systematischen Fehler wird der sehr schwer zu finden ist, zumal er u.U. gar nicht gleich bemerkt wird.

        Wenn jedoch für port kein Default konfiguriert ist, fliegt eine Ex und der Trace zeigt auf die Zeile in welcher sich der Tippfehler befindet.

        Freundschaft 😉