Nimettyjä elementtitunnuksia voidaan kutsua JavaScript Globals PlatoBlockchain Data Intelligenceksi. Pystysuuntainen haku. Ai.

Nimettyjä elementtitunnuksia voidaan kutsua JavaScriptin globaaleiksi

Tiesitkö, että DOM-elementit, joissa on tunnus, ovat käytettävissä JavaScriptissä globaaleina muuttujina? Se on yksi niistä asioista, joka on ollut olemassa ikuisesti, mutta kaivaudun siihen todella ensimmäistä kertaa.

Jos tämä on ensimmäinen kerta, kun kuulet siitä, varaudu! Näemme sen toiminnassa yksinkertaisesti lisäämällä tunnuksen HTML-elementtiin:

Normaalisti määritämme uuden muuttujan käyttämällä querySelector("#cool") or getElementById("cool") valitaksesi kyseisen elementin:

var el = querySelector("#cool");

Mutta meillä on itse asiassa jo pääsy siihen #cool ilman sitä rigamoraalia:

Joten mikä tahansa id - tai name attribuuttia – HTML-koodissa voidaan käyttää JavaScriptin avulla window[ELEMENT_ID]. Jälleen kerran, tämä ei ole aivan "uusi", mutta se on todella harvinaista nähdä.

Kuten arvata saattaa, globaalin laajuuden käyttäminen nimettyjen viitteiden avulla ei ole paras idea. Jotkut ihmiset ovat alkaneet kutsua tätä "maailmanlaajuiseksi saastuttajaksi". Selvitämme miksi näin on, mutta ensin…

Jotkut yhteydet

Tämä lähestymistapa on HTML-määrityksessä, jossa se on kuvattu "nimetyksi pääsyksi Window esine."

Internet Explorer oli ensimmäinen, joka otti ominaisuuden käyttöön. Myös kaikki muut selaimet lisäsivät sen. Gecko oli tuolloin ainoa selain, joka ei tukenut sitä suoraan standarditilassa, vaan päätti tehdä siitä kokeellisen ominaisuuden. Oli epäröintiä toteuttaa se ollenkaan, mutta se oli edettiin selaimen yhteensopivuuden nimissä (Gecko jopa yritti vakuuttaa WebKit siirtääksesi sen pois standarditilasta) ja lopulta pääsi standarditilaan Firefox 14:ssä.

Yksi asia, jota ei ehkä tiedetä hyvin, on se, että selaimet joutuivat ottamaan käyttöön muutamia varotoimenpiteitä – vaihtelevalla menestyksellä – varmistaakseen, että luodut globaalit eivät rikkoisi verkkosivua. Yksi tällainen toimenpide on…

Muuttuva varjostus

Luultavasti mielenkiintoisin osa tätä ominaisuutta on, että nimetyt elementtiviitteet eivät sitä tee varjostaa olemassa olevia globaaleja muuttujia. Joten jos DOM-elementillä on id joka on jo määritetty globaaliksi, se ei ohita olemassa olevaa. Esimerkiksi:


  
    window.foo = "bar";
  


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

Ja myös päinvastoin:

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

Tämä toiminta on välttämätöntä, koska se mitätöi vaaralliset ohitukset, kuten

, joka muuten aiheuttaisi ristiriidan mitätöimällä alert API. Tämä turvatekniikka saattaa hyvinkin olla syy, miksi sinä – jos olet kuten minä – opit tästä ensimmäistä kertaa.

Kanne nimettyjä globaaleja vastaan

Aiemmin sanoin, että globaalien nimettyjen elementtien käyttäminen viitteinä ei ehkä ole paras idea. Siihen on monia syitä, mikä TJ VanToll on käsitellyt asiaa hienosti blogissaan ja teen yhteenvedon tähän:

  • Jos DOM muuttuu, niin myös viittaus. Tämä tekee joistakin todella "hauraita" (spesifikaation termi se) koodia, jossa HTML:n ja JavaScriptin välinen ero voi olla liikaa.
  • Satunnaiset viittaukset ovat aivan liian helppoja. Yksinkertainen kirjoitusvirhe saattaa hyvinkin päätellä nimetyn globaalin viittaamisen ja antaa odottamattomia tuloksia.
  • Se toteutetaan eri tavalla selaimissa. Meidän pitäisi esimerkiksi päästä käsiksi ankkuriin an id - esimerkiksi — mutta jotkin selaimet (eli Safari ja Firefox) palauttavat a ReferenceError konsolissa.
  • Se ei ehkä palauta sitä, mitä ajattelet. Teknisten tietojen mukaan, kun DOM:ssa on useita samannimisen elementin esiintymiä - esimerkiksi kaksi esiintymää

    - selaimen pitäisi palauttaa an HTMLCollection joukolla esiintymiä. Firefox kuitenkin palauttaa vain ensimmäisen esiintymän. Toisaalta, speksi sanoo meidän pitäisi käyttää yhtä esiintymää an id joka tapauksessa elementin puussa. Mutta se ei estä sivua toimimasta tai mitään vastaavaa.

  • Ehkä siinä on suorituskustannukset? Tarkoitan, selaimen täytyy tehdä tuo viiteluettelo ja ylläpitää sitä. Pari ihmistä teki testejä tässä StackOverflow-ketjussa, jossa nimetyt globaalit itse asiassa olivat tehokkaampi yhdessä testissä ja vähemmän suorituskykyinen uudemmassa testissä.

Muita näkökohtia

Oletetaan, että torjumme kritiikin nimettyjen globaalien käyttöä vastaan ​​ja käytämme niitä joka tapauksessa. Kaikki on hyvin. Mutta on joitain asioita, joita sinun kannattaa harkita tehdessäsi.

Polyfillit

Niin äärimmäiseltä kuin se kuulostaakin, tämän tyyppiset yleiset tarkistukset ovat tyypillinen monitäytteiden asetusvaatimus. Katso seuraava esimerkki, jossa asetamme evästeen käyttämällä uutta CookieStore API, polyfilling se selaimissa, jotka eivät vielä tue sitä:


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

Tämä koodi toimii täydellisesti Chromessa, mutta aiheuttaa seuraavan virheen Safarissa:

TypeError: cookieStore.set is not a function

Safarista puuttuu tuki CookieStore API tämän kirjoituksen jälkeen. Tämän seurauksena monitäytettä ei käytetä, koska img elementin ID luo globaalin muuttujan, joka on ristiriidassa cookieStore globaali.

JavaScript API -päivitykset

Voimme kääntää tilanteen ja löytää vielä yhden ongelman, jossa selaimen JavaScript-moottorin päivitykset voivat rikkoa nimetyn elementin globaalit viittaukset.

Esimerkiksi:


  
  
    window.BarcodeDetector.focus();
  

Tämä komentosarja nappaa viittauksen syöttöelementtiin ja kutsuu focus() sen päällä. Se toimii oikein. Silti emme tiedä miten pitkä se toimii edelleen.

Näet, globaali muuttuja, jota käytämme viittaamaan syöttöelementtiin, lakkaa toimimasta heti, kun selaimet alkavat tukea BarcodeDetector API. Siinä vaiheessa, window.BarcodeDetector global ei enää ole viittaus syöttöelementtiin ja .focus() heittää "window.BarcodeDetector.focus ei ole toiminto" -virhe.

Bonus: Kaikki nimetyt elementit eivät tuota globaaleja viittauksia

Haluatko kuulla jotain hauskaa? Vamman loukkaamiseksi nimetyt elementit ovat käytettävissä globaaleina muuttujina vain, jos nimet eivät sisällä muuta kuin kirjainta. Selaimet eivät luo yleistä viittausta elementille, jonka tunnus sisältää erikoismerkkejä ja numeroita, kuten esim hello-world ja item1.

Yhteenveto

Tehdään yhteenveto, miten tähän päädyttiin:

  • Kaikki yleisimmät selaimet luovat automaattisesti maailmanlaajuiset viittaukset jokaiseen DOM-elementtiin, jossa on an id (tai joissain tapauksissa a name attribuutti).
  • Näihin elementteihin pääsy maailmanlaajuisten viittausten kautta on epäluotettavaa ja mahdollisesti vaarallista. Käyttää querySelector or getElementById sen sijaan.
  • Koska maailmanlaajuiset viittaukset luodaan automaattisesti, niillä voi olla sivuvaikutuksia koodiisi. Tämä on hyvä syy välttää sen käyttöä id ominaisuus, ellet todella tarvitse sitä.

Loppujen lopuksi on luultavasti hyvä idea välttää nimettyjen globaalien käyttämistä JavaScriptissä. Lainasin aiemmin spesifikaatiota siitä, kuinka se johtaa "hauraaseen" koodiin, mutta tässä on koko teksti, joka vie asian kotiin:

Yleissääntönä tähän luottaminen johtaa hauraaseen koodiin. Mitkä tunnukset päätyvät tähän sovellusliittymään, voivat vaihdella ajan myötä, kun esimerkiksi verkkoalustaan ​​lisätään uusia ominaisuuksia. Käytä tämän sijaan document.getElementById() or document.querySelector().

Mielestäni se tosiasia, että HTML-spesifikaatio itse suosittelee pysymään poissa tästä ominaisuudesta, puhuu puolestaan.

Aikaleima:

Lisää aiheesta CSS-temppuja