Nimega elementide ID-sid saab nimetada JavaScripti globaalseteks PlatoBlockchain Data Intelligenceks. Vertikaalne otsing. Ai.

Nimega elementide ID-sid saab nimetada JavaScripti globaalseteks

Kas teadsite, et ID-ga DOM-i elemendid on JavaScriptis globaalsete muutujatena kättesaadavad? See on üks neist asjadest, mis on olnud olemas nagu igavesti, kuid ma süvenen sellesse esimest korda.

Kui kuulete sellest esimest korda, võtke end ette! Näeme seda töös lihtsalt lisades HTML-i elemendile ID:

Tavaliselt määratleksime uue muutuja kasutades querySelector("#cool") or getElementById("cool") selle elemendi valimiseks:

var el = querySelector("#cool");

Kuid tegelikult on meil juba juurdepääs #cool ilma selle rigamoraalita:

Niisiis, ükskõik milline id - või name atribuut – HTML-is pääseb sellele JavaScriptis juurde, kasutades window[ELEMENT_ID]. Jällegi, see pole just "uus", kuid see on tõesti haruldane.

Nagu võite arvata, pole nimeliste viidetega globaalsele ulatusele juurdepääs kõige parem idee. Mõned inimesed on hakanud seda nimetama "globaalseks saastajaks". Uurime, miks see nii on, kuid kõigepealt…

Mingi kontekst

See lähenemine on HTML-i spetsifikatsioonis kirjeldatud, kus seda kirjeldatakse kui „nimega juurdepääsu Window objekt."

Internet Explorer oli esimene, kes selle funktsiooni kasutusele võttis. Ka kõik teised brauserid lisasid selle. Gecko oli sel ajal ainus brauser, mis ei toetanud seda otse standardrežiimis, vaid otsustas muuta selle eksperimentaalseks funktsiooniks. Kõhkles, kas seda üldse ellu viia, aga siiski liikus brauseri ühilduvuse nimel edasi (Gecko isegi proovis veenda WebKiti et teisaldada see standardrežiimist välja) ja lõpuks jõudis see Firefox 14 standardrežiimi.

Üks asi, mis ei pruugi olla hästi teada, on see, et brauserid pidid rakendama mõningaid ettevaatusabinõusid – vahelduva eduga – tagamaks, et loodud globaalsed veebilehed ei rikuks. Üks selline meede on…

Muutuv varjutus

Selle funktsiooni kõige huvitavam osa on ilmselt see, et nimeliste elementide viited seda ei tee varjutada olemasolevaid globaalseid muutujaid. Seega, kui DOM-i elemendil on id mis on juba määratletud kui globaalne, ei alista see olemasolevat. Näiteks:


  
    window.foo = "bar";
  


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

Ja tõsi on ka vastupidine:

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

See käitumine on hädavajalik, sest see tühistab ohtlikud alistamised, näiteks

, mis muidu tekitaks vastuolu, tühistades selle alert API. See kaitsetehnika võib väga hästi olla põhjus, miks te – kui olete nagu mina – sellest esimest korda teada saate.

Kohtuasi nimeliste globaalsete vastu

Varem ütlesin, et globaalsete nimedega elementide kasutamine viidetena ei pruugi olla parim idee. Sellel on palju põhjuseid, mis TJ VanToll on oma ajaveebis kenasti kajastanud ja teen kokkuvõtte siin:

  • Kui DOM muutub, muutub ka viide. See muudab mõne väga "hapraks" (spetsifikatsiooni termin selle jaoks) kood, kus HTML-i ja JavaScripti probleemide eraldamine võib olla liiga suur.
  • Juhuslikud viited on liiga lihtsad. Lihtne kirjaviga võib väga hästi lõppeda nimega globaalsele viitamisele ja anda ootamatuid tulemusi.
  • Seda rakendatakse brauserites erinevalt. Näiteks peaks meil olema juurdepääs ankrule ankruga id — nt — kuid mõned brauserid (nimelt Safari ja Firefox) tagastavad a ReferenceError konsoolis.
  • See ei pruugi tagastada seda, mida arvate. Spetsifikatsiooni kohaselt, kui DOM-is on sama nimega elemendi mitu eksemplari – näiteks kaks

    — brauser peaks tagastama an HTMLCollection eksemplaride massiiviga. Firefox aga tagastab ainult esimese eksemplari. Siis jälle, spetsifikatsioon ütleb me peaksime kasutama ühte eksemplari an id elemendi puus nagunii. Kuid see ei takista lehe töötamist ega muud sellist.

  • Äkki on esinemiskulu? Ma mõtlen, et brauser peab selle viidete loendi koostama ja seda säilitama. Paar inimest tegid testid selles StackOverflow lõimes, kus nimelised globaalsed tegelikult olid tulemuslikum ühes testis ja uuemas testis vähem tulemuslik.

Täiendavad kaalutlused

Oletame, et tõrjume kriitikat nimeliste globaalide kasutamise vastu ja kasutame neid ikkagi. See on kõik hea. Kuid on mõningaid asju, mida võiksite kaaluda.

Polütäidised

Nii äärmuslikult kui see ka ei kõlaks, on seda tüüpi globaalsed kontrollid polütäite jaoks tüüpiline seadistusnõue. Vaadake järgmist näidet, kus seadsime küpsise, kasutades uut CookieStore API, täites selle brauserites, mis seda veel ei toeta:


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

See kood töötab Chrome'is suurepäraselt, kuid annab Safaris järgmise vea:

TypeError: cookieStore.set is not a function

Safaril puudub tugi selle jaoks CookieStore API selle kirjutamise seisuga. Selle tulemusena ei rakendata polüfilli, kuna img elemendi ID loob globaalse muutuja, mis on vastuolus cookieStore globaalne

JavaScript API värskendused

Saame olukorra ümber pöörata ja leida veel ühe probleemi, kus brauseri JavaScripti mootori värskendused võivad rikkuda nimetatud elemendi globaalseid viiteid.

Näiteks:


  
  
    window.BarcodeDetector.focus();
  

See skript haarab viite sisendelemendile ja kutsub esile focus() selle kallal. See töötab õigesti. Siiski me ei tea, kuidas pikk see töötab edasi.

Näete, globaalne muutuja, mida kasutame sisendelemendile viitamiseks, lakkab töötamast niipea, kui brauserid hakkavad BarcodeDetector API. Sel hetkel, window.BarcodeDetector globaalne ei ole enam viide sisendelemendile ja .focus() viskab "window.BarcodeDetector.focus ei ole funktsioon” viga.

Boonus: mitte kõik nimega elemendid ei loo globaalseid viiteid

Kas soovite kuulda midagi naljakat? Vigastuse solvamiseks on nimega elemendid globaalsete muutujatena juurdepääsetavad ainult siis, kui nimed ei sisalda midagi peale tähe. Brauserid ei loo globaalset viidet elemendile, mille ID sisaldab erimärke ja numbreid (nt hello-world ja item1.

Järeldus

Võtame kokku, kuidas me siia jõudsime:

  • Kõik suuremad brauserid loovad automaatselt globaalsed viited igale DOM-i elemendile tähega id (või mõnel juhul a name atribuut).
  • Nendele elementidele juurdepääs globaalsete viidete kaudu on ebausaldusväärne ja potentsiaalselt ohtlik. Kasutage querySelector or getElementById asemel.
  • Kuna globaalsed viited genereeritakse automaatselt, võivad need teie koodile avaldada mõningaid kõrvalmõjusid. See on hea põhjus, et vältida selle kasutamist id atribuut, kui te seda tõesti ei vaja.

Päeva lõpuks on ilmselt hea mõte vältida nimega globaalsete elementide kasutamist JavaScriptis. Tsiteerisin varem spetsifikatsiooni selle kohta, kuidas see "haprale" koodile viib, kuid siin on täistekst, mis juhib punkti:

Üldreeglina põhjustab sellele tuginemine koodi rabeda. Millised ID-d selle API-ga lõpuks vastendatakse, võivad aja jooksul muutuda, kuna näiteks veebiplatvormile lisatakse uusi funktsioone. Selle asemel kasutage document.getElementById() or document.querySelector().

Arvan, et fakt, et HTML-i spetsifikatsioon ise soovitab sellest funktsioonist eemale hoida, räägib enda eest.

Ajatempel:

Veel alates CSSi trikid