Benannte Element-IDs können als JavaScript Globals PlatoBlockchain Data Intelligence referenziert werden. Vertikale Suche. Ai.

Benannte Element-IDs können als JavaScript-Globals referenziert werden

Wussten Sie, dass DOM-Elemente mit IDs in JavaScript als globale Variablen zugänglich sind? Es ist eines dieser Dinge, die es schon ewig gibt, aber ich beschäftige mich zum ersten Mal wirklich damit.

Wenn Sie zum ersten Mal davon hören, machen Sie sich bereit! Wir können es in Aktion sehen, indem wir einfach eine ID zu einem Element in HTML hinzufügen:

Normalerweise würden wir eine neue Variable mit definieren querySelector("#cool") or getElementById("cool") um dieses Element auszuwählen:

var el = querySelector("#cool");

Aber wir haben eigentlich schon Zugriff auf #cool ohne diese Rigamorale:

Also irgendwelche id - oder name Attribut, für diese Angelegenheit — im HTML kann in JavaScript mit zugegriffen werden window[ELEMENT_ID]. Auch dies ist nicht gerade „neu“, aber es ist wirklich ungewöhnlich zu sehen.

Wie Sie vielleicht erraten haben, ist der Zugriff auf den globalen Gültigkeitsbereich mit benannten Referenzen nicht die beste Idee. Einige Leute nennen dies den „globalen Umweltverschmutzer“. Wir werden darauf eingehen, warum das so ist, aber zuerst …

Irgendein Kontext

Dieser Ansatz ist in der HTML-Spezifikation beschrieben, wo es als „named access on the Window Objekt."

Internet Explorer war der erste, der diese Funktion implementierte. Alle anderen Browser haben es ebenfalls hinzugefügt. Gecko war zu dieser Zeit der einzige Browser, der es nicht direkt im Standardmodus unterstützte, sondern sich stattdessen dafür entschied, es zu einer experimentellen Funktion zu machen. Es gab Bedenken, es überhaupt umzusetzen, aber es im Namen der Browserkompatibilität vorangetrieben (Gecko hat es sogar versucht WebKit überzeugen um es aus dem Standardmodus zu verschieben) und schaffte es schließlich in Firefox 14 in den Standardmodus.

Eine Sache, die vielleicht nicht so bekannt ist, ist, dass Browser einige Vorsichtsmaßnahmen treffen mussten – mit unterschiedlichem Erfolg – ​​um sicherzustellen, dass generierte Globals die Webseite nicht beschädigen. Eine solche Maßnahme ist …

Variable Abschattung

Der wahrscheinlich interessanteste Teil dieser Funktion ist, dass Verweise auf benannte Elemente dies nicht tun existierende globale Variablen schattieren. Wenn also ein DOM-Element eine id das bereits als global definiert ist, überschreibt das vorhandene nicht. Zum Beispiel:


  
    window.foo = "bar";
  


  
I won't override window.foo
console.log(window.foo); // Prints "bar"

Und das Gegenteil gilt auch:

I will be overridden :(
window.foo = "bar"; console.log(window.foo); // Prints "bar"

Dieses Verhalten ist wichtig, da es gefährliche Überschreibungen wie z

, die andernfalls einen Konflikt erzeugen würde, indem die ungültig gemacht wird alert API. Diese Sicherungstechnik ist möglicherweise der Grund, warum Sie – wenn Sie wie ich sind – zum ersten Mal davon erfahren.

Der Fall gegen Named Globals

Ich habe vorhin gesagt, dass die Verwendung von global benannten Elementen als Referenzen vielleicht nicht die beste Idee ist. Dafür gibt es viele Gründe, die TJ VanToll hat in seinem Blog gut darüber berichtet und ich fasse hier zusammen:

  • Wenn sich das DOM ändert, ändert sich auch die Referenz. Das macht einige wirklich „spröde“ (der Begriff der Spezifikation dafür) Code, bei dem die Trennung zwischen HTML und JavaScript zu weit gehen könnte.
  • Versehentliche Referenzen sind viel zu einfach. Ein einfacher Tippfehler kann sehr wohl dazu führen, dass auf einen benannten globalen Wert verwiesen wird, und Ihnen unerwartete Ergebnisse liefern.
  • Es ist in Browsern unterschiedlich implementiert. Zum Beispiel sollten wir in der Lage sein, mit an auf einen Anker zuzugreifen id - z.B — aber einige Browser (nämlich Safari und Firefox) geben a zurück ReferenceError in der Konsole.
  • Es gibt möglicherweise nicht das zurück, was Sie denken. Gemäß der Spezifikation, wenn es mehrere Instanzen desselben benannten Elements im DOM gibt – sagen wir, zwei Instanzen von

    — Der Browser sollte eine zurückgeben HTMLCollection mit einem Array der Instanzen. Firefox gibt jedoch nur die erste Instanz zurück. Dann wieder, die spezifikation sagt wir sollten eine Instanz von an verwenden id sowieso im Baum eines Elements. Dies wird jedoch nicht verhindern, dass eine Seite funktioniert oder ähnliches.

  • Vielleicht gibt es Leistungskosten? Ich meine, der Browser muss diese Referenzliste erstellen und pflegen. Ein paar Leute haben Tests durchgeführt in diesem StackOverflow-Thread, wo Named Globals tatsächlich waren leistungsfähiger in einem Test und weniger leistungsfähig in einem neueren Test.

Weitere Überlegungen

Nehmen wir an, wir werfen die Kritik gegen die Verwendung von Named Globals weg und verwenden sie trotzdem. Es ist alles gut. Aber es gibt einige Dinge, die Sie vielleicht berücksichtigen sollten, wenn Sie dies tun.

Füllmaterialien

So grenzwertig es auch klingen mag, diese Arten von globalen Prüfungen sind eine typische Setup-Anforderung für Polyfills. Sehen Sie sich das folgende Beispiel an, in dem wir ein Cookie mit dem new CookieStore API, polyfilling es auf Browsern, die es noch nicht unterstützen:


  
  
    // Polyfill the CookieStore API if not yet implemented.
    // https://developer.mozilla.org/en-US/docs/Web/API/CookieStore
    if (!window.cookieStore) {
      window.cookieStore = myCookieStorePolyfill;
    }
    cookieStore.set("foo", "bar");
  

Dieser Code funktioniert in Chrome einwandfrei, löst aber in Safari den folgenden Fehler aus:

TypeError: cookieStore.set is not a function

Safari hat keine Unterstützung für die CookieStore API zum Zeitpunkt dieses Schreibens. Infolgedessen wird die Füllwatte nicht aufgetragen, da die img Element-ID erstellt eine globale Variable, die mit der kollidiert cookieStore global.

JavaScript-API-Updates

Wir können die Situation umkehren und ein weiteres Problem finden, bei dem Aktualisierungen der JavaScript-Engine des Browsers die globalen Referenzen eines benannten Elements beschädigen können.

Beispielsweise:


  
  
    window.BarcodeDetector.focus();
  

Dieses Skript greift auf einen Verweis auf das Eingabeelement zu und ruft auf focus() darauf. Es funktioniert korrekt. Trotzdem wissen wir nicht wie lange es wird weiter funktionieren.

Sie sehen, die globale Variable, die wir verwenden, um auf das Eingabeelement zu verweisen, wird nicht mehr funktionieren, sobald Browser beginnen, die zu unterstützen BarcodeDetector API. An diesem Punkt ist die window.BarcodeDetector global ist kein Verweis mehr auf das Eingabeelement und .focus() wirft ein „window.BarcodeDetector.focus ist keine Funktion“ Fehler.

Bonus: Nicht alle benannten Elemente erzeugen globale Referenzen

Willst du etwas Lustiges hören? Um das Ganze noch schlimmer zu machen, sind benannte Elemente nur dann als globale Variablen zugänglich, wenn die Namen nur Buchstaben enthalten. Browser erstellen keine globale Referenz für ein Element mit einer ID, die Sonderzeichen und Zahlen enthält, wie z hello-world und item1.

Zusammenfassung

Fassen wir zusammen, wie wir hierher gekommen sind:

  • Alle gängigen Browser erstellen automatisch globale Verweise auf jedes DOM-Element mit einem id (oder in manchen Fällen a name Attribut).
  • Der Zugriff auf diese Elemente über ihre globalen Referenzen ist unzuverlässig und potenziell gefährlich. Verwenden querySelector or getElementById stattdessen.
  • Da globale Verweise automatisch generiert werden, können sie einige Nebenwirkungen auf Ihren Code haben. Das ist ein guter Grund, die Verwendung von zu vermeiden id Attribut, es sei denn, Sie brauchen es wirklich.

Letztendlich ist es wahrscheinlich eine gute Idee, benannte Globals in JavaScript zu vermeiden. Ich habe die Spezifikation zuvor zitiert, wie sie zu „brüchigem“ Code führt, aber hier ist der vollständige Text, um den Punkt zu verdeutlichen:

Wenn Sie sich darauf verlassen, führt dies in der Regel zu sprödem Code. Welche IDs letztendlich dieser API zugeordnet werden, kann im Laufe der Zeit variieren, wenn beispielsweise neue Funktionen zur Webplattform hinzugefügt werden. Verwenden Sie stattdessen document.getElementById() or document.querySelector().

Ich denke, die Tatsache, dass die HTML-Spezifikation selbst empfiehlt, sich von dieser Funktion fernzuhalten, spricht für sich.

Zeitstempel:

Mehr von CSS-Tricks