![]() |
Gewinnspiel zu 10 Jahren SELFHTML: Auflösung |
Zu beantworten waren diverse kniffelige Fragen rund um das World Wide Web. Unter den besten Einsendern wurden fünf Exemplare des Buches
Professionelle Websites von Stefan Münz verlost.
Die Fragen wurden unter den SELFHTML Developern zusammengetragen. Dabei wurde darauf geachtet, kniffelige Fragen zu stellen, die sich nicht unbedingt nur mit kurzem Nachschlagen zu beantworten waren, sondern zu eigener Recherche in den entsprechenden Spezifikationen und zum Selberdenken anregen sollten.
Die Gewinner: Folgende Teilnehmer haben jeweils ein Buch gewonnen.
Die richtigen Antworten sind fett markiert.
new Date(1960,23,4,23,59,60)new Date(1960,22,33,23,59,59,999)new Date(1961,11,4,23,60,-1)new Date(1961,12,4,23,59,59,59)Erläuterung: Die Parameter, die der
Date-Konstruktor entgegennimmt, sind Jahr, Monat, Tag, Stunden, Minuten, Sekunden, Millisekunden. Die erste Lösungsmöglichkeit scheint falsche Angaben zu beinhalten: Als Monat ist 23 angegeben, als Sekunden 60 - ein Jahr hat aber nur 12 Monate und den Zeitpunkt 23:59:60 gibt es nicht (abgesehen von Schaltsekunden, die in JavaScript aber keine Rolle spielen). Dies ist aber kein Problem für JavaScript, denn die überschüssigen Monate und Sekunden werden auf die Jahre bzw. Minuten aufgerechnet. So ist new Date(1960,23,4,23,59,60) identisch mit new Date(1961,11,5,0,0,0). Das ist der 5. Dezember 1961, 0:00 Uhr (denn die Zählung des Monats beginnt mit 0 = Januar und endet mit 11 = Dezember). Ähnliche Verwirrspiele mit übergroßen Angaben, die JavaScript automatisch intern in Millisekunden umrechnet und eine Summe bildet (Unix-Timestamp), werden bei den folgenden Lösungsmöglichkeiten getrieben. Hier ist kein großes Nachdenken und Nachrechnen angebracht, sondern ein simples Ausprobieren, indem man sich das zurückgelieferte Datumsobjekt mit window.alert() ausgeben lässt. Auf diese Weise kommt man auf die Lösung new Date(1961,11,4,23,60,-1): 4. Dezember 1961 plus 23 Stunden und 60 Minuten ergibt 5. Dezember 1961, 0:00 Uhr. Durch die negative Sekundenangabe wird eine Sekunde substrahiert, Ergebnis: 4. Dezember 1961, 23:59:59 Uhr.
Der praktische Nutzen dieser Angabe von scheinbar falschen Werten zeigt sich bei folgender Frage:
Wie kann man das Datum des jeweils auf einen Tag folgenden Tages herausbekommen? Man könnte zwar zu einem bestehenden Datumsobjekt soviel Millisekunden addieren, wie ein Tag hat. Einfacher und zuverlässiger ist jedoch das Addieren von 1 zum Tageswert:
var heute = new Date();
var morgen = new Date(heute.getFullYear(), heute.getMonth(), heute.getDate() + 1);
window.alert("Morgen ist der " + morgen.getDate() + "." + (morgen.getMonth() + 1) + ".");
instanceoftypeofinvalueofErläuterung: Der
instanceof-Operator liefert zurück, ob ein Objekt eine Instanz eines anderen prototypischen Objekts ist. Beispiel:
var meinArray = new Array(1,2,3); window.alert(meinArray instanceof Array);
typeof ist der
Operator zur Typenbestimmung.
Der in-Operator wird bei
for-in-Schleifen verwendet.
Einen valueof-Operator gibt es nicht in JavaScript bzw. ECMAScript (siehe auch
Reservierte Wörter). Lediglich eine Methode valueOf() existiert bei allen Objekten. Deren Gebrauch ist in in der Praxis nahezu unnötig.
MathNumberStringRegExpErläuterung: Prototypen sind vergleichbar mit Klassen in anderen objektorientierten Sprachen. Den Prototypen Number, String und RegExp können neue Methoden und Eigenschaften angehängt werden, die sich dann auf alle Zahlwerte, Zeichenketten bzw. reguläre Ausdrücke auswirken. Von diesen Prototypen sind also Instanzen möglich (z.B. exp = new RegExp("\d+")).
Math hingegen ist ein festes Objekt, das unveränderliche Eigenschaften und Methoden für mathematische Berechnungen zur Verfügung stellt. Es gibt also keine von Math abgeleiteten Objekte (Instanzen). Daher ist es unmöglich, Math als Prototyp zu erweitern.
parseInt("5,5") * 2 = 10String(12) + 4 = 16Math.floor(4.25) * 82 = 328parseInt(16,16) * 2 = 44 Erläuterung: Die Funktion
parseInt() beim der ersten Lösungsmöglichkeit wandelt den String-Wert "5,5" in den ganzzahligen Number-Wert 5 um. Die Gleichung 5 * 2 = 10 ist korrekt. String(12) wandelt den Number-Wert 12 in den String "12" um. Bei dem Ausdruck "12" + 4 wird der Number-Wert 4 automatisch zu einem String-Wert umgewandelt, da der Operator + als
Operator zur Zeichenkettenverknüpfung interpretiert wird, sobald ein Operand ein String-Wert ist. "12" + 4 ergibt also den String-Wert "124" und nicht 16. Diese Lösungsmöglichkeit ist daher die gesuchte falsche.
Math.floor() gibt die nächstniedrige Ganzzahl zurück, daher gilt Math.floor(4.25) = 4, womit die dritte Lösungsmöglichkeit korrekt ist. Bei der vierten Lösungsmöglichkeit wird parseInt() eine Basis des verwendeten Zahlensystems als zweiter Parameter übergeben - in diesem Fall 16, besser bekannt als Hexadezimalsystem. 0x16 hexadezimal ist 22 im Dezimalsystem, daher geht auch die vierte Gleichung auf.
BOOLEANTINYINT(1)CHAR(1)TIMESTAMPErläuterung: Der Datentyp BOOLEAN entspricht seit MySQL Version 4.1.0 dem Datetypen TINYINT(1). Als eigenständigen Datentypen wird
es ihn jedoch erst in späteren Versionen geben.
Siehe auch:
MySQL Reference Manual: Overview of Numeric Types
LEFT OUTER JOINCROSS JOINLEFT INNER JOINNATURAL LEFT OUTER JOINErläuterung:
Wie im MySQL-Manual zur
Syntax von JOIN zu lesen ist, gibt es keinen LEFT INNER JOIN. LEFT INNER JOIN ergibt auch keinerlei Sinn da INNER aussagt,
dass die Daten auf beiden Seiten vorhanden sein müssen, eine
Seitenangabe widerspricht dem.
Erläuterung: Bei Transaktionen geht es darum, dass mehrere Statements ausgeführt werden, als seien sie nur ein einziges. Es ist dabei unterschiedlich stark ausgeprägt, wieviel andere Prozesse davon sehen können bei lesendem Zugriff. Read New, also das Lesen von neu hinzugekommenen Datensätzen, ergibt in diesem Zusammenhang keinerlei Sinn.
GROUP BYWHEREFROMHAVINGErläuterung:
GROUP BY fasst Zeilen mit identischen Werten in den aufgelisteten Feldern zusammen. WHERE beinhaltet Kriterien, die vor der Gruppierung geprüft werden können, HAVING beinhaltet Kriterien, die erst nach der Gruppierung geprüft werden können und FROM spezifiziert die verwendeten Quellen.
Erläuterung: Daten sind unsortiert abgelegt. Man könnte sie zwar anhand des Primärschlüssels sortieren, dies ist jedoch überflüssig da sie beliebig umsortiert werden. Ohne Sortierung können entstehende Lücken mit anderen Datensätzen gefüllt werden.
Es gibt jedoch Ausnahmen, im Falle eines Clusters werden die Daten entsprechend der Reihenfolge eines Indizes abgelegt, um die Lesegeschwindigkeit zu erhöhen, wenn die Daten anhand dieses Kriteriums gefiltert werden
102202302402Erläuterung: Die
Übersicht der HTTP-Status-Codes zeigt, dass es 102 nicht gibt und erklärt gleichzeitig, was die anderen Statuscodes bedeuten.
/index.htmlindex.htmlhttp://www.example.org/http://www.example.org/index.htmlhttp://www.example.org/index.html#topErläuterung: Der Location-Header wird bei HTTP-Weiterleitungen genutzt, um dem User-Agent (Browser, Suchmaschinenrobot usw.) die neue Adresse mitzuteilen, also das Ziel der Weiterleitung. Ein solcher Location-Header muss gemäß dem HTTP-Standard eine sogenannte absolute URI (siehe etwa
mit vollständigen URIs referenzieren) beinhalten. Die ersten beiden Lösungsmöglichkeiten sind demnach falsch, wenngleich viele Browser diese falschen Angaben tolerieren und den Benutzer trotzdem weiterleiten. Die dritte und vierte Adresse sind absolute URIs und somit korrekt.
Eine Falle haben wir bei der fünften Adresse eingebaut: Der HTTP-Standard bezieht sich auf eine spezielle Definition "absoluteURI" von RFC 2396, das die Syntax von URI definiert. Die Autoren hatten allerdings vergessen, sogenannte "fragment identifier", also Ankernamen in diesen Location-Adressen zuzulassen - was sinnvoll ist, damit man den Benutzer an eine bestimmte Stelle eines Dokuments weiterleiten kann. In einem
Errata wird dieser Fehler genannt und soll in Zukunft korrigiert werden.
301302303307Erläuterung: Ursprünglich war der 302-Statuscode so konzipiert, dass ein Browser auf einen anderen URI weitergeleitet wird, wo er die gleiche Anfrage noch einmal wiederholen sollte. Allerdings haben fast alle Browserhersteller das anders interpretiert und fast alle Browser führten dann eine GET-Anfrage durch, anstatt die ursprüngliche Anfrage zu wiederholen. Im
HTTP-1.1-Standard werden aus diesem Grund zwei neue Statuscodes eingeführt: 303 und 307.
Nach 303 soll immer eine GET-Anfrage folgen, nach 307 soll die ursprüngliche Anfrage wiederholt werden - also genau das, was 302 eigentlich tun sollte. 303 ist somit auf jeden Fall falsch. 302 wird alleine durch die Tatsache, dass im HTTP-Standard 307 eingeführt wird, der genau das tun soll, was 302 eigentlich hätte tun sollen, quasi obsolet erklärt - man hätte 307 ja nicht einführen müssen. A.J. Flavell hat in seinem Artikel
Redirect in response to POST transaction praktische Untersuchungen zum Thema durchgeführt. Diese zeigen, dass ein 302-Statuscode in allen Browsern heutzutage eine GET-Anfrage zur Folge hat, ein 301-Statuscode in über der Hälfte der Fälle eine GET-Anfrage zur Folge hat. Somit scheidet 301 aus praktischen Gründen aus, 302 ebenso, der jedoch auch schon im Standard quasi fallen gelassen wird. 303 ist sowieso falsch. 307 ist extra dafür eingeführt worden, dass die ursprüngliche Anfrage wiederholt wird und in den praktischen Fällen führt er am ehesten zum gewünschten Ergebnis - somit ist 307 die richtige Antwort.
chunkedgzipcompressdeflateErläuterung: Im
HTTP-1.1-Standard steht:
All HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer-coding
Somit ist chunked die richtige Antwort.
$foo = 83.69.76.70;83.697670den Stringwert "SELF"einen Hostnamen, z.B. www.google.de (automatische Namensauflösung)eine Referenz auf die Speicheradresse $5345:4C46Erläuterung: In
perldoc perldata steht unter "Version Strings", dass v83.69.76.70 ein sogenannter "Version-String" wäre, bei dem jeder Zahlenblock ein Zeichen der Zeichenkette darstellt. 83, 69, 76 und 70 sind die
ASCII-Codes für die Zeichen S, E, L und F. Da mehr als ein Punkt verwendet wurde, kann das v auch weggelassen werden. Hinweis: Perl 5.8 ist die letzte Perl-Version, die diese Syntax unterstützen wird, da sie viel Konfusion hervorgerufen hat.
@sorted = sort values %myhash;@sorted = sort { $myhash{$a} <=> $myhash{$b} } values %myhash;@sorted = sort { $myhash{$a} <=> $myhash{$b} } keys %myhash;Gar nicht, weil Hashes im Gegensatz zu Arrays ungeordnet im Speicher abgelegt werden und somit nicht sortiert werden könnenErläuterung: In
perldoc perlfaq4 wird gezeigt, wie das funktioniert.
65536 Zeichen1 Zeichen (Char-Wert)sehr viel, abhängig von der Hardwareausstattung und Systemarchitektur16,7 Millionen ZeichenErläuterung: Aus
perldoc perldata:
A scalar is a single string (of any size, limited only by the available memory), number, or a reference to something (which will be discussed in perlref).
Somit gibt es keine Begrenzung durch Perl selbst, sondern nur durch das Betriebsystem und die Hardware.
$x = 1; while ($x < 20) { $x = $x * 2; } print "$x\n";20322116Erläuterung: Am Anfang wird die Variable $x auf 1 gesetzt. Danach wird $x so lange mit 2 Multipliziert, bis der Wert größer als 20 ist. Danach wird $x ausgegeben. Vor der Schleife hat $x den Wert 1, somit wird die Schleife durchlaufen, danach hat es den Wert 2, danach wird die Schleife wieder durchlaufen... Irgendwann hat $x den Wert 16 und die Schleife darf somit noch einmal durchlaufen werden, nach der Schleife ist $x dann jedoch 32 und somit darf die Schleife nicht noch einmal durchlaufen werden. Nach der Schleife wird $x ausgegeben, was den aktuellen Wert 32 besitzt.
581315Erläuterung:
SELFHTML: Knotentypen, Achsen und Pfade. Durch Nachzählen der Anzahl an Zeilen in der Tabelle mit den Achsen kommt man auf die korrekte Lösung 13.
//::@*[ ]Erläuterung:
Adressierung mit Positionsangabe und Bedingungen. Neben kapitel//absatz steht:
Die Syntax // wird auch als recursive descent operator bezeichnet.
Erläuterung: Zur Einführung:
XML und XML-Derivate.
Document Type DefinitionDistributed Template DevelopmentDocument Type DeclarationDocument Template DefinitionErläuterung:
SELFHTML: Dokumentyp-Definitionen
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>encodingstandaloneversionErläuterung:
XML-Deklaration. Lediglich die Versionsangabe ist zwingend notwendig. Die Kodierungsangabe ist notwendig, wenn das Dokument nicht wie in diesem Fall die Default-Zeichenkodierung UTF-8 verwendet (bzw. wenn keine Byte-Order-Markierung vorliegt, die die Verwendung von UTF-16 anzeigt).
Siehe auch
Standardzeichensatz und Unicode-Unterstützung.
:link, :active, :hover, :visited, :focus:link, :active, :focus, :hover, :visited:link, :visited, :focus, :hover, :active:active, :link, :hover, :focus, :visitedErläuterung: In SELFHTML wird zwar eine
andere Reihenfolge genannt, allerdings ist hier eigenes Denken gefordert. Die
Kaskade fordert, dass bei gleicher Spezifizität der Selektoren die Reihenfolge über die angewandte Regel entscheidet. Später im Quelltext vorkommende Regeln überschreiben dann früher im Quelltext vorkommende Regeln. Jetzt muss man sich die Wirkungsweise der genannten Pseudoklassen ins Gedächnis rufen, jede Pseudoklasse wirkt in dieser Reihenfolge auf weniger Elemente als die vorgehende, sie ist weniger generell. Das heißt, die speziellen Pseudoklassen überschreiben die allgemeinen.
a:link bezieht sich auf alle noch nicht besuchten Verweise.a:visited bezieht sich auf alle bereits besuchten Verweise.a:focus bezieht sich auf die Verweise, die den aktuellen Fokus haben, also z.B. durch die Tabulator-Taste angesprungen wurden.a:hover bezieht sich auf alle Verweise, über denen der Mauszeiger schwebt.a:active bezieht sich auf alle Verweise, die aktiviert sind, sei es durch einen Mausklick oder durch Drücken der Eingabetaste nach einer Fokussierung.Bei der ersten Antwort überschreibt die Pseudoklasse :visited die spezielleren Pseudoklassen :active und :hover. Die für diese Pseudoklassen deklarierten CSS-Regeln würden also bei bereits besuchten Links nicht mehr wirksam werden. Die zweite Antwort hat dasselbe Problem.
Bei der vierten Antwort steht die Pseudoklasse :link nach der Pseudoklasse :active. Die für :active deklarierten CSS-Regeln kommen also nicht zur Anwendung. Desweiteren besteht wieder das Problem, das :visited ganz am Ende steht, also die Formatierungen für besuchte Links unabhängig vom sonstigen Pseudoklassen immer Vorrang haben.
Nur die dritte Antwortmöglichkeit stuft von generelleren Pseudoklassen zu spezielleren ab: Zuerst wird für alle Verweise eine Formatierung beschrieben. Wenn die Verweise besucht sind, gelten die Formatierungen für :visited anstelle der für :link. Wenn der Verweis den Fokus hat, überschreiben die Formatierungen für :focus alle vorhergehenden Formatierungen. Wenn über dem Verweis zusätzlich noch der Mauszeiger schwebt, gibt es mit :hover wieder neue Formatierungen; die Formatierungen für angeklickte Verweise (:active) überschreiben wieder alle anderen.
displayclippositionwidthErläuterung:
Die z-index-Eigenschaft: Im ersten Satz wird gleich erwähnt, dass die position-Angabe notwendig ist, damit z-index Wirkung zeigt.
displaywidthcontentcolorErläuterung:
Farbangaben: window ist ein Anwender-relatives Farbwort und entspricht der Hintergrundfarbe von Dokumentfenstern.
handw-resizetextwaitErläuterung:
cursor (Mauszeiger): Der Internet Explorer bis Version 5.5 kennt pointer nicht, dafür jedoch hand als möglichen Wert für die cursor-Angabe, der jedoch nicht im Standard enthalten ist.
vertical-align:top;writing-mode:tb-rl;text-align:vertical;Erläuterung: Es gibt eine
proprietäre Microsoft-Erweiterung writing-mode des CSS-Standards, die voraussichtlich
in CSS3 übernommen werden wird. Mit dem Wert tb-rl ("top to bottom, right to left") ist es möglich, Text vertikal darstellen zu lassen (aktuell zumindest im Internet Explorer).