A megnevezett elemazonosítók JavaScript Globals PlatoBlockchain Data Intelligence néven hivatkozhatók. Függőleges keresés. Ai.

A megnevezett elemazonosítókra JavaScript Globalsként hivatkozhatunk

Tudta, hogy az azonosítókkal rendelkező DOM-elemek globális változóként érhetők el a JavaScriptben? Ez egyike azoknak a dolgoknak, amelyek örökké léteznek, de most először mélyedek el benne.

Ha most hall először róla, készüljön fel! A műveletet egyszerűen úgy láthatjuk, ha hozzáadunk egy azonosítót egy elemhez a HTML-ben:

Általában egy új változót definiálunk a használatával querySelector("#cool") or getElementById("cool") az elem kiválasztásához:

var el = querySelector("#cool");

De valójában már hozzáférünk #cool a rigamorale nélkül:

Szóval bármelyik id - vagy name attribútum, ami azt illeti – a HTML-ben JavaScript segítségével érhető el window[ELEMENT_ID]. Ismétlem, ez nem éppen „új”, de nagyon ritka.

Ahogy sejtheti, a globális hatókör elérése elnevezett hivatkozásokkal nem a legjobb ötlet. Vannak, akik ezt „globális szennyezőnek” nevezik. Kitérünk arra, hogy miért, de először…

Néhány összefüggés

Ez a megközelítés az a HTML specifikációban vázolt, ahol a leírása a következő: „névvel rendelkező hozzáférés a Window tárgy."

Az Internet Explorer volt az első, amely bevezette a funkciót. Az összes többi böngésző is hozzáadta. Abban az időben a Gecko volt az egyetlen böngésző, amely nem támogatta közvetlenül szabványos módban, inkább kísérleti funkcióvá tette. Habozás volt egyáltalán megvalósítani, de ez előrelépett a böngésző kompatibilitás nevében (Gecko meg is próbálta meggyőzni a WebKit hogy kilépjen a szabványos módból), és végül a Firefox 14 szabványos módba lépett.

Egy dolog, ami talán nem köztudott, az az, hogy a böngészőknek néhány óvintézkedést kellett bevezetniük – változó sikerrel – annak biztosítására, hogy a generált globálisok ne törjék meg a weboldalt. Az egyik ilyen intézkedés…

Változó árnyékolás

Valószínűleg ennek a funkciónak a legérdekesebb része az, hogy az elnevezett elemre vonatkozó hivatkozások nem árnyékolja a meglévő globális változókat. Tehát, ha egy DOM elemnek van egy id amely már globálisként van definiálva, akkor nem írja felül a meglévőt. Például:


  
    window.foo = "bar";
  


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

És ennek az ellenkezője is igaz:

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

Ez a viselkedés elengedhetetlen, mert semmissé teszi a veszélyes felülírásokat, mint pl

, amely egyébként ütközést okozna a alert API. Lehetséges, hogy ez a védelmi technika lehet az oka annak, hogy Ön – ha olyan, mint én – először tanul erről.

Az ügy nevezett globálisok ellen

Korábban azt mondtam, hogy a globális elnevezésű elemek hivatkozásként való használata talán nem a legjobb ötlet. Ennek sok oka van, ami TJ VanToll szépen leírta a blogját és itt összefoglalom:

  • Ha a DOM megváltozik, akkor a hivatkozás is változik. Ez egyeseket igazán „törékennyé” tesz (a specifikáció kifejezése számára) kódot, ahol a HTML és a JavaScript közötti aggályok szétválasztása túl sok lehet.
  • A véletlen hivatkozások túl egyszerűek. Egy egyszerű elírás nagyon jól zárhatja a megnevezett globális hivatkozást, és váratlan eredményeket adhat.
  • A böngészőkben másképp van megvalósítva. Például egy horgonyhoz hozzá kell férnünk egy id - például — de egyes böngészők (nevezetesen a Safari és a Firefox) visszaadják a ReferenceError a konzolban.
  • Lehet, hogy nem adja vissza azt, amit gondol. A specifikáció szerint, ha ugyanannak a nevű elemnek több példánya van a DOM-ban – mondjuk két példánya

    — a böngészőnek vissza kell adnia egy HTMLCollection a példányok tömbjével. A Firefox azonban csak az első példányt adja vissza. Aztán megint, a specifikáció szerint egy példányt kellene használnunk az an id amúgy egy elem fájában. Ez azonban nem akadályozza meg egy oldal működését vagy hasonlókat.

  • Lehet, hogy van teljesítményköltsége? Úgy értem, a böngészőnek el kell készítenie a hivatkozási listát, és karban kell tartania. Pár ember tesztelt ebben a StackOverflow szálban, ahol a nevesített globálisok voltak valójában hatékonyabb egy tesztben és a kevésbé teljesítő egy újabb tesztben.

További megfontolások

Tegyük fel, hogy elhárítjuk a megnevezett globalok használata elleni kritikákat, és mindenképp használjuk őket. Minden rendben van. De van néhány dolog, amit érdemes megfontolni.

Polifills

Bármilyen szélsőségesen hangzik is, az ilyen típusú globális ellenőrzések tipikus beállítási követelmény a többkitöltéseknél. Tekintse meg a következő példát, ahol cookie-t állítunk be az új használatával CookieStore API, többszörös kitöltéssel olyan böngészőkön, amelyek még nem támogatják:


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

Ez a kód tökéletesen működik a Chrome-ban, de a Safariban a következő hibát okozza:

TypeError: cookieStore.set is not a function

A Safari nem támogatja a CookieStore API jelen pillanatban. Ennek eredményeként a polifill nem kerül alkalmazásra, mert a img elemazonosító létrehoz egy globális változót, amely ütközik a cookieStore globális.

JavaScript API frissítések

Megfordíthatjuk a helyzetet, és találhatunk egy újabb problémát, ahol a böngésző JavaScript-motorjának frissítései megtörhetik egy megnevezett elem globális hivatkozásait.

Például:


  
  
    window.BarcodeDetector.focus();
  

Ez a szkript megragad egy hivatkozást a bemeneti elemre, és meghívja focus() Rajta. Megfelelően működik. Ennek ellenére nem tudjuk, hogyan hosszú tovább fog működni.

Látja, a globális változó, amelyet a bemeneti elemre hivatkozunk, leáll, amint a böngészők támogatják a BarcodeDetector API. Ezen a ponton a window.BarcodeDetector global többé nem lesz hivatkozás a bemeneti elemre és .focus() dob egy "window.BarcodeDetector.focus nem funkció” hiba.

Bónusz: Nem minden elnevezett elem generál globális hivatkozásokat

Szeretnél valami vicceset hallani? A sérülés sértése érdekében a megnevezett elemek csak akkor érhetők el globális változóként, ha a nevek csak betűt tartalmaznak. A böngészők nem hoznak létre globális hivatkozást olyan elemhez, amelynek azonosítója speciális karaktereket és számokat tartalmaz, mint pl hello-world és a item1.

Következtetés

Foglaljuk össze, hogyan jutottunk el idáig:

  • Az összes főbb böngésző automatikusan globális hivatkozásokat hoz létre minden DOM-elemhez egy id (vagy bizonyos esetekben a name tulajdonság).
  • Ezekhez az elemekhez globális referenciáik révén hozzáférni megbízhatatlan és potenciálisan veszélyes. Használat querySelector or getElementById helyette.
  • Mivel a globális hivatkozások automatikusan generálódnak, előfordulhatnak mellékhatások a kódra. Ez jó ok arra, hogy ne használja a id tulajdonság, hacsak nincs rá igazán szüksége.

A nap végén valószínűleg érdemes elkerülni a nevesített globálisok használatát a JavaScriptben. Korábban idéztem a specifikációt arról, hogy ez hogyan vezet „törékeny” kódhoz, de itt van a teljes szöveg, hogy a lényeget megmutassa:

Általános szabály, hogy erre hagyatkozva törékennyé válik a kód. Az, hogy mely azonosítók kerülnek végül ehhez az API-hoz, idővel változhatnak, mivel például új funkciókat adnak hozzá a webes platformhoz. Ehelyett használja document.getElementById() or document.querySelector().

Azt hiszem, az a tény, hogy maga a HTML-specifikáció azt javasolja, hogy távol maradjon ettől a funkciótól, önmagáért beszél.

Időbélyeg:

Még több CSS trükkök