Na ID-je poimenovanih elementov se lahko sklicujete kot na JavaScript Globals PlatoBlockchain Data Intelligence. Navpično iskanje. Ai.

ID-ji poimenovanih elementov se lahko sklicujejo kot globalni JavaScript

Ali ste vedeli, da so elementi DOM z ID-ji dostopni v JavaScriptu kot globalne spremenljivke? To je ena tistih stvari, ki so prisotne že od nekdaj, vendar se prvič zares poglobim v to.

Če prvič slišite za to, se pripravite! Delovanje lahko vidimo preprosto tako, da elementu v HTML dodamo ID:

Običajno bi novo spremenljivko definirali z uporabo querySelector("#cool") or getElementById("cool") da izberete ta element:

var el = querySelector("#cool");

Toda dejansko že imamo dostop do #cool brez te rigamorale:

Torej, katerikoli id - ali name kar zadeva atribut – v HTML-ju lahko dostopate v JavaScriptu z uporabo window[ELEMENT_ID]. Še enkrat, to ni ravno "novo", vendar je res neobičajno videti.

Kot morda ugibate, dostop do globalnega obsega z imenovanimi referencami ni najboljša ideja. Nekateri so to poimenovali »globalni onesnaževalec«. Ugotovili bomo, zakaj je tako, a najprej …

Nekaj ​​konteksta

Ta pristop je opisano v specifikaciji HTML, kjer je opisan kot »imenovani dostop na Window objekt."

Internet Explorer je prvi implementiral to funkcijo. Dodali so ga tudi vsi drugi brskalniki. Gecko je bil v tistem času edini brskalnik, ki ga ni podpiral neposredno v standardnem načinu, temveč se je odločil, da bo postal poskusna funkcija. Bilo je oklevanja, da bi ga sploh uveljavili, a je premaknil naprej v imenu združljivosti brskalnikov (Gecko je celo poskušal prepričati WebKit da ga premaknete iz standardnega načina) in sčasoma prešli v standardni način v Firefoxu 14.

Ena stvar, ki morda ni dobro znana, je, da so morali brskalniki uvesti nekaj previdnostnih ukrepov – z različnimi stopnjami uspeha – da zagotovijo, da ustvarjeni globali ne pokvarijo spletne strani. Eden takih ukrepov je…

Spremenljivo senčenje

Verjetno najbolj zanimiv del te funkcije je, da sklice na poimenovane elemente ne zasenči obstoječe globalne spremenljivke. Torej, če ima element DOM id ki je že definiran kot globalni, ne bo preglasil obstoječega. Na primer:


  
    window.foo = "bar";
  


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

In tudi obratno velja:

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

To vedenje je bistveno, ker izniči nevarne preglasitve, kot je npr

, kar bi sicer povzročilo konflikt z razveljavitvijo alert API. Ta zaščitna tehnika je morda prav razlog, zakaj - če ste takšni kot jaz - prvič izveste o tem.

Zadeva proti imenovanim globalom

Prej sem rekel, da uporaba globalnih poimenovanih elementov kot referenc morda ni najboljša ideja. Za to obstaja veliko razlogov, ki TJ VanToll je lepo zapisal na svojem blogu in tukaj bom povzel:

  • Če se spremeni DOM, se spremeni tudi sklic. Zaradi tega so nekateri res "krhki" (termin spec za to) kodo, pri kateri je lahko ločevanje pomislekov med HTML in JavaScript preveliko.
  • Naključna sklicevanja so preveč enostavna. Preprosta tipkarska napaka se lahko zelo dobro konča s sklicevanjem na poimenovan global in vam da nepričakovane rezultate.
  • V brskalnikih je implementiran drugače. Na primer, morali bi imeti možnost dostopa do sidra z id - npr — vendar nekateri brskalniki (in sicer Safari in Firefox) vrnejo a ReferenceError v konzoli.
  • Morda ne bo vrnilo tega, kar mislite. V skladu s specifikacijo, ko je v DOM več primerkov istega poimenovanega elementa – recimo dva primerka

    — brskalnik bi moral vrniti an HTMLCollection z nizom primerkov. Firefox pa vrne samo prvo instanco. Ampak, specifikacija pravi morali bi uporabiti en primerek an id tako ali tako v drevesu elementa. Toda s tem ne boste preprečili delovanja strani ali česa podobnega.

  • Morda obstaja strošek uspešnosti? Mislim, brskalnik mora narediti ta seznam referenc in ga vzdrževati. Nekaj ​​ljudi je opravilo teste v tej niti StackOverflow, kjer so bili dejansko imenovani globali bolj zmogljiv v enem testu in manj zmogljiv v novejšem testu.

Dodatni premisleki

Recimo, da zavržemo kritike proti uporabi poimenovanih globalov in jih vseeno uporabimo. Vse je v redu. Obstaja pa nekaj stvari, ki bi jih morda želeli upoštevati.

Polifili

Naj se sliši še tako nenavadno, so te vrste globalnih preverjanj tipična zahteva za nastavitev polifillov. Oglejte si naslednji primer, kjer piškotek nastavimo z uporabo new CookieStore API, izpolnjevanje v brskalnikih, ki tega še ne podpirajo:


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

Ta koda deluje popolnoma v redu v Chromu, vendar vrže to napako v Safariju:

TypeError: cookieStore.set is not a function

Safari nima podpore za CookieStore API od tega pisanja. Posledično se polifil ne nanese, ker img element ID ustvari globalno spremenljivko, ki je v nasprotju z cookieStore globalno.

Posodobitve JavaScript API

Lahko obrnemo situacijo in najdemo še eno težavo, pri kateri lahko posodobitve mehanizma JavaScript brskalnika prekinejo globalne reference imenovanega elementa.

Na primer:


  
  
    window.BarcodeDetector.focus();
  

Ta skript zgrabi sklic na vhodni element in prikliče focus() na njem. Deluje pravilno. Še vedno pa ne vemo, kako dolgi še naprej bo delovalo.

Vidite, globalna spremenljivka, ki jo uporabljamo za sklicevanje na vhodni element, bo prenehala delovati takoj, ko bodo brskalniki začeli podpirati BarcodeDetector API. Na tej točki je window.BarcodeDetector global ne bo več referenca na vhodni element in .focus() bo vrgel "window.BarcodeDetector.focus ni funkcija«.

Bonus: vsi poimenovani elementi ne ustvarjajo globalnih referenc

Želite slišati nekaj smešnega? Za dodatno žalitev so poimenovani elementi dostopni kot globalne spremenljivke samo, če imena ne vsebujejo nič drugega kot črko. Brskalniki ne bodo ustvarili globalne reference za element z ID-jem, ki vsebuje posebne znake in številke, na primer hello-world in item1.

zaključek

Naj povzamemo, kako smo prišli sem:

  • Vsi večji brskalniki samodejno ustvarijo globalne reference na vsak element DOM z id (ali v nekaterih primerih a name atribut).
  • Dostop do teh elementov prek njihovih globalnih referenc je nezanesljiv in potencialno nevaren. Uporaba querySelector or getElementById namesto tega.
  • Ker se globalne reference generirajo samodejno, imajo lahko nekatere stranske učinke na vašo kodo. To je dober razlog, da se izogibate uporabi id atribut, razen če ga res potrebujete.

Na koncu dneva je verjetno dobra ideja, da se izogibate uporabi poimenovanih globalov v JavaScriptu. Prej sem citiral specifikacijo o tem, kako to vodi do "krhke" kode, toda tukaj je celotno besedilo, ki pove bistvo:

Splošno pravilo je, da bo zanašanje na to povzročilo krhko kodo. Kateri ID-ji se na koncu preslikajo v ta API, se lahko sčasoma razlikujejo, ko se na primer spletni platformi dodajo nove funkcije. Namesto tega uporabite document.getElementById() or document.querySelector().

Menim, da dejstvo, da sama specifikacija HTML priporoča izogibanje tej funkciji, govori samo zase.

Časovni žig:

Več od Triki CSS