Navngitte element-ID-er kan refereres til som JavaScript Globals PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Navngitte element-ID-er kan refereres til som JavaScript-globale

Visste du at DOM-elementer med ID-er er tilgjengelige i JavaScript som globale variabler? Det er en av de tingene som har eksistert for alltid, men jeg graver virkelig i det for første gang.

Hvis dette er første gang du hører om det, vær klar! Vi kan se det i aksjon ved å legge til en ID til et element i HTML:

Normalt vil vi definere en ny variabel ved å bruke querySelector("#cool") or getElementById("cool") for å velge det elementet:

var el = querySelector("#cool");

Men vi har faktisk allerede tilgang til #cool uten den strengheten:

Så, hvilken som helst id - eller name attributt, for den saks skyld - i HTML kan du få tilgang til i JavaScript ved å bruke window[ELEMENT_ID]. Igjen, dette er ikke akkurat "nytt", men det er virkelig uvanlig å se.

Som du kanskje gjetter, er det ikke den beste ideen å få tilgang til det globale omfanget med navngitte referanser. Noen mennesker har kommet til å kalle dette «forurenseren med globalt omfang». Vi skal komme inn på hvorfor det er det, men først...

Noe kontekst

Denne tilnærmingen er skissert i HTML-spesifikasjonen, der det er beskrevet som "navngitt tilgang på Window gjenstand."

Internet Explorer var den første som implementerte funksjonen. Alle andre nettlesere la det også til. Gecko var den eneste nettleseren på den tiden som ikke støttet den direkte i standardmodus, og valgte i stedet å gjøre den til en eksperimentell funksjon. Det var nøling med å implementere det i det hele tatt, men det gikk videre i navnet på nettleserkompatibilitet (Gecko prøvde til og med det overbevise WebKit for å flytte den ut av standardmodus) og kom til slutt til standardmodus i Firefox 14.

En ting som kanskje ikke er godt kjent, er at nettlesere måtte sette på plass noen få forholdsregler – med ulik grad av suksess – for å sikre at genererte globaler ikke ødelegger nettsiden. Et slikt tiltak er...

Variabel skyggelegging

Sannsynligvis den mest interessante delen av denne funksjonen er at navngitte elementreferanser ikke gjør det skygge eksisterende globale variabler. Så hvis et DOM-element har en id som allerede er definert som en global, vil den ikke overstyre den eksisterende. For eksempel:


  
    window.foo = "bar";
  


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

Og det motsatte er også sant:

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

Denne oppførselen er viktig fordi den opphever farlige overstyringer som f.eks

, som ellers ville skape en konflikt ved å ugyldiggjøre alert API. Denne beskyttelsesteknikken kan meget vel være grunnen til at du - hvis du er som meg - lærer om dette for første gang.

Saken mot navngitte globaler

Tidligere sa jeg at å bruke globale navngitte elementer som referanser kanskje ikke er den beste ideen. Det er mange grunner til det, som TJ VanToll har dekket fint på bloggen sin og jeg vil oppsummere her:

  • Hvis DOM endres, gjør referansen det også. Det gjør noen virkelig "skjøre" (spesifikasjonens begrep for det) kode hvor separasjonen av bekymringer mellom HTML og JavaScript kan være for mye.
  • Tilfeldige referanser er altfor enkle. En enkel skrivefeil kan meget vel ende opp med å referere til en navngitt global og gi deg uventede resultater.
  • Det er implementert annerledes i nettlesere. For eksempel skal vi kunne få tilgang til et anker med en id - f.eks - men noen nettlesere (nemlig Safari og Firefox) returnerer en ReferenceError i konsollen.
  • Det vil kanskje ikke returnere det du tror. I henhold til spesifikasjonen, når det er flere forekomster av det samme navngitte elementet i DOM - si, to forekomster av

    — nettleseren skal returnere en HTMLCollection med en rekke instanser. Firefox returnerer imidlertid bare den første instansen. Så igjen, spesifikasjonen sier vi burde bruke en forekomst av en id i et elements tre uansett. Men å gjøre det stopper ikke en side fra å fungere eller noe sånt.

  • Kanskje det er en ytelseskostnad? Jeg mener, nettleseren må lage den listen over referanser og vedlikeholde den. Et par personer kjørte tester i denne StackOverflow-tråden, hvor navngitte globaler faktisk var mer ytelse i én test og mindre presterende i en nyere test.

Ytterligere hensyn

La oss si at vi kaster bort kritikken mot å bruke navngitte globaler og bruker dem likevel. Det er bra. Men det er noen ting du kanskje bør vurdere mens du gjør.

Polyfills

Selv om det kan høres ut som det kan høres ut, er disse typene globale kontroller et typisk oppsettskrav for polyfills. Sjekk ut følgende eksempel der vi setter en informasjonskapsel ved å bruke den nye CookieStore API, polyfilling det i nettlesere som ikke støtter det ennå:


  
  
    // 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");
  

Denne koden fungerer helt fint i Chrome, men gir følgende feilmelding i Safari.:

TypeError: cookieStore.set is not a function

Safari mangler støtte for CookieStore API når dette skrives. Som et resultat påføres ikke polyfillet fordi img element ID oppretter en global variabel som kolliderer med cookieStore global.

JavaScript API-oppdateringer

Vi kan snu situasjonen og finne enda et problem der oppdateringer til nettleserens JavaScript-motor kan bryte et navngitt elements globale referanser.

For eksempel:


  
  
    window.BarcodeDetector.focus();
  

Det skriptet henter en referanse til inngangselementet og påkaller focus() på den. Det fungerer riktig. Likevel vet vi ikke hvordan lang det vil fortsette å fungere.

Du skjønner, den globale variabelen vi bruker for å referere til input-elementet vil slutte å fungere så snart nettlesere begynner å støtte BarcodeDetector API. På det tidspunktet window.BarcodeDetector global vil ikke lenger være en referanse til input-elementet og .focus() vil kaste en "window.BarcodeDetector.focus er ikke en funksjon" feil.

Bonus: Ikke alle navngitte elementer genererer globale referanser

Vil du høre noe morsomt? For å legge fornærmelse til skaden, er navngitte elementer tilgjengelige som globale variabler bare hvis navnene ikke inneholder annet enn bokstav. Nettlesere vil ikke opprette en global referanse for et element med en ID som inneholder spesialtegn og tall, som f.eks hello-world og item1.

konklusjonen

La oss oppsummere hvordan vi kom hit:

  • Alle store nettlesere oppretter automatisk globale referanser til hvert DOM-element med en id (eller, i noen tilfeller, a name Egenskap).
  • Å få tilgang til disse elementene gjennom deres globale referanser er upålitelig og potensielt farlig. Bruk querySelector or getElementById i stedet.
  • Siden globale referanser genereres automatisk, kan de ha noen bivirkninger på koden din. Det er en god grunn til å unngå å bruke id attributt med mindre du virkelig trenger det.

På slutten av dagen er det sannsynligvis en god idé å unngå å bruke navngitte globaler i JavaScript. Jeg siterte spesifikasjonen tidligere om hvordan den fører til "skjør" kode, men her er hele teksten for å drive poenget hjem:

Som en generell regel vil det å stole på dette føre til sprø kode. Hvilke IDer som ender opp med å kartlegge til denne API-en kan variere over tid, ettersom nye funksjoner legges til for eksempel nettplattformen. I stedet for dette, bruk document.getElementById() or document.querySelector().

Jeg tror det faktum at HTML-spesifikasjonen i seg selv anbefaler å holde seg unna denne funksjonen taler for seg selv.

Tidstempel:

Mer fra CSS triks