Warum ist document.all falsch?

Lesezeit: 6 Minuten

document.all ist ein nicht primitives Objekt im DOM, das falsch ist.

Zum Beispiel macht dieser Code nichts:

if (document.all) {
    alert("hello");
}

Kann jemand erklären, warum das so ist?

  • Moderne Browser implementieren dieses veraltete Ding nicht mehr. Es ist ein IE “Standard”, Opera “shims” es auch.

    – Bergi

    27. April 2012 um 11:54 Uhr


  • @Nanne die Frage ist: kann jemand erklären, warum der Code nichts tut. Wenn es nicht implementiert ist, ist if falsch und es passiert nichts. Ich denke also, es ist eine Antwort.

    Benutzer1150525

    27. April 2012 um 12:02 Uhr

  • Aber die Frage besagte auch, dass wir es mit einem Nicht-Null-Objekt zu tun haben? Vielleicht habe ich das falsch gelesen, aber ich bin davon ausgegangen, dass das im Test bedeutet, dass es da war, aber nur nicht ausgelöst hat?

    – Nanne

    27. April 2012 um 12:05 Uhr

  • @Nanne: OK, ich habe die Frage jetzt verstanden. Ich habe eine weitere Antwort hinzugefügt.

    – Bergi

    27. April 2012 um 12:26 Uhr


  • In Kyle Simpsons Buch gibt es dazu eine gute tl;dr-Erklärung: github.com/getify/You-Dont-Know-JS/blob/master/… (scrollen Sie nach unten zur Überschrift „Warum?!“).

    – imrek

    29. Juni 2016 um 14:59 Uhr


Warum ist documentall falsch
Mathias Bynens

Haftungsausschluss: Ich bin der Typ, der die Frage getwittert hat, die zu diesem Thread geführt hat 🙂 Es war eine Frage, die ich in meinem stellen und beantworten würde Front-Trends sprechen. Ich schrieb diesen Tweet 5 Minuten bevor ich auf die Bühne ging.


Die Frage, die ich gestellt habe, ist die folgende.

Die ECMAScript-Spezifikation definiert ToBoolean() wie folgt:

ToBoolean(condition), Folie aus meinem Front-Trends 2012 Vortrag

Wie Sie sehen können, sind alle nicht-primitiven Objekte (dh alle Objekte, die keine booleschen Werte, Zahlen, Zeichenfolgen, undefinedoder null) sind wahrheitsgemäß gemäß der Spezifikation. Im DOM gibt es jedoch eine Ausnahme – ein DOM-Objekt, das falsch ist. Weißt du welcher das ist?

Die Antwort ist document.all. Die HTML-Spezifikation sagt:

Die all Attribut muss ein zurückgeben HTMLAllCollection verwurzelt an der Document Knoten, dessen Filter auf alle Elemente passt.

Das für alle zurückgegebene Objekt weist mehrere ungewöhnliche Verhaltensweisen auf:

Der Benutzeragent muss sich so verhalten, als ob die ToBoolean() -Operator in JavaScript konvertiert das Objekt, für das zurückgegeben wird all zum false Wert.

Der Benutzeragent muss so handeln, als ob er für die Zwecke der == und !=
Operatoren in JavaScript das Objekt, für das zurückgegeben wird all ist gleich dem
undefined Wert.

Der Benutzeragent muss so handeln, dass die typeof -Operator in JavaScript gibt die Zeichenfolge zurück 'undefined' wenn es auf das zurückgegebene Objekt angewendet wird
all.

Diese Anforderungen stellen einen vorsätzlichen Verstoß gegen die zum Zeitpunkt des Schreibens aktuelle JavaScript-Spezifikation (ECMAScript Edition 5) dar. Die JavaScript-Spezifikation erfordert, dass die ToBoolean() Operator konvertiert alle Objekte in die true Wert und hat keine Bestimmungen für Gegenstände, die so tun, als ob sie es wären undefined für die Zwecke bestimmter Betreiber. Diese Verletzung wird durch den Wunsch nach Kompatibilität mit zwei Klassen von Legacy-Inhalten motiviert: eine, die das Vorhandensein von verwendet document.all als eine Möglichkeit, alte Benutzeragenten zu erkennen, und eine, die nur diese alten Benutzeragenten unterstützt und die verwendet
document.all Objekt, ohne vorher auf seine Anwesenheit zu testen.

Damit, document.all ist die einzige offizielle Ausnahme von dieser ECMAScript-Regel. (In Oper, document.attachEvent usw. sind auch falsch, aber das ist nirgendwo angegeben.)

Der obige Text erklärt, warum dies getan wurde. Aber hier ist ein Beispiel-Code-Snippet, das auf alten Webseiten sehr häufig vorkommt und das weiter veranschaulichen wird:

if (document.all) {
  // code that uses `document.all`, for ancient browsers
} else if (document.getElementById) {
  // code that uses `document.getElementById`, for “modern” browsers
}

Im Grunde schon lange document.all wurde auf diese Weise verwendet, um alte Browser zu erkennen. Weil document.all Getestet wird allerdings erst, modernere Browser, die beide Eigenschaften bieten, würden trotzdem in der landen document.all Codepfad. In modernen Browsern würden wir lieber verwenden document.getElementByIdnatürlich, aber da die meisten Browser immer noch haben document.all (aus anderen Abwärtskompatibilitätsgründen) die else würde nie zugegriffen werden, wenn document.all war Wahrheit. Wäre der Code anders geschrieben, wäre dies kein Problem:

if (document.getElementById) {
  // code that uses `document.getElementById`, for “modern” browsers
} else if (document.all) {
  // code that uses `document.all`, for ancient browsers
}

Aber leider macht es ein Großteil des vorhandenen Codes umgekehrt.

Die einfachste Lösung für dieses Problem ist einfach zu machen document.all in Browsern falsch sein, die es immer noch imitieren.

  • Ziemlich komplizierte Antwort für eine veraltete Funktion.

    – adrianp

    23. Mai 2013 um 13:27 Uhr

  • @adrian Willkommen im Web, wo alles wegen veralteter Funktionen kompliziert ist 🙂

    – Mathias Bynens

    3. Oktober 2013 um 9:07 Uhr

  • Aber im Oktober 17 wurde dieser Hinweis entfernt, obwohl das Verhalten bis heute gleich bleibt …

    – Jyrkka

    2. April 2020 um 6:55 Uhr

  • Und das haben wir mariusschulz.com/blog/… smh

    – Will

    16. November 2020 um 19:51 Uhr


1647176709 953 Warum ist documentall falsch
D. Pardal

ES2019-Update

Es gibt jetzt eine [[IsHTMLDDA]]interner Steckplatz für Objekte:

Ein [[IsHTMLDDA]]Interner Slot kann auf implementierungsdefinierten Objekten vorhanden sein. Objekte mit einem [[IsHTMLDDA]]internen Steckplatz verhalten sich wie undefined in den abstrakten Operationen ToBoolean und Abstract Equality Comparison und bei Verwendung als Operand für die typeof Operator.

Der HTML-Standard wurde ebenfalls aktualisiert, um diesen internen Slot für Objekte hinzuzufügen, die die implementieren HTMLAllCollection Schnittstelle:

Objekte, die die HTMLAllCollection-Schnittstelle implementieren, sind ältere Plattformobjekte mit einem zusätzlichen [[Call]]interne Methode, die im folgenden Abschnitt beschrieben wird. Sie haben auch eine [[IsHTMLDDA]]interner Steckplatz.


Der Grund für diesen Wahnsinn ist in dieser Anmerkung im HTML-Standard angegeben:

Diese besonderen Verhaltensweisen werden durch den Wunsch nach Kompatibilität mit zwei Klassen von Legacy-Inhalten motiviert: eine, die das Vorhandensein von document.all als eine Möglichkeit, alte Benutzeragenten zu erkennen, und eine, die nur diese alten Benutzeragenten unterstützt und die verwendet document.all Objekt, ohne vorher auf seine Anwesenheit zu testen.

Im Grunde möchte der Standard also mit diesen beiden Arten von Code kompatibel sein:

  • Code, der überprüft, ob er in Internet Explorer ausgeführt wird, um seine nicht standardmäßigen Funktionen zu verwenden, wie z document.all und Activex;

    if (document.all) {
        useActiveXStuff();
    }
    
  • Code, der davon ausgeht, dass er in Internet Explorer ausgeführt wird und verwendet document.all.

    document.all["my-button"].onclick = function () {
        alert("hi");
    };
    

1647176709 369 Warum ist documentall falsch
Bergi

Moderne Browser implementieren dieses veraltete Ding nicht mehr. Es wurde von IE eingeführt, aber die meisten anderen “shimen” es, um kompatibel zu sein.

Um die Browsererkennung zu ermöglichen (früher konnte man IE von NN unterscheiden, indem man auf document.all) Während die document.all-Syntax unterstützt wird, haben andere Browser die “seltsame” Implementierung vorgenommen typeof document.all gibt undefiniert zurück.

Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false

Bevor FF die Unterstützung dafür eingestellt hat, zeigte es auch ein seltsames Verhalten, wie in angegeben diese Nachricht. Möglicherweise finden Sie weitere Interna in Mozilla-Fehler Nr. 412247.

Da ist auch ein sehr langer Faden im W3C-Mailinglistenarchiv, beginnend mit http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html

Kurz gesagt, es geht darum, dass BEIDE dieser Codebeispiele funktionieren. Browser müssen dies tun, damit alte Webseiten weiterhin funktionieren.

Probe 1

// Internet Explorer
if (document.all) {
    useActiveX()
}
// Netscape Navigator
else {
    useOldButStillWorkingCode()
}

Probe 2

document.all.output.innerHTML = 'Hello, world!'

997750cookie-checkWarum ist document.all falsch?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy