È possibile fare riferimento agli ID degli elementi denominati come JavaScript Globals PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.

Gli ID elemento denominati possono essere referenziati come globali JavaScript

Sapevi che gli elementi DOM con ID sono accessibili in JavaScript come variabili globali? È una di quelle cose che esistono da sempre, ma ci sto davvero scavando per la prima volta.

Se è la prima volta che ne senti parlare, preparati! Possiamo vederlo in azione semplicemente aggiungendo un ID a un elemento in HTML:

Normalmente, definiremmo una nuova variabile usando querySelector("#cool") or getElementById("cool") per selezionare quell'elemento:

var el = querySelector("#cool");

Ma in realtà abbiamo già accesso a #cool senza quel rigamorale:

Quindi, qualsiasi id - o name attributo, del resto — nell'HTML è possibile accedere in JavaScript utilizzando window[ELEMENT_ID]. Ancora una volta, questo non è esattamente "nuovo", ma è davvero raro da vedere.

Come puoi immaginare, l'accesso all'ambito globale con riferimenti denominati non è la migliore idea. Alcune persone sono arrivate a chiamarlo "l'inquinatore di portata globale". Vedremo perché è così, ma prima...

Qualche contesto

Questo approccio è descritto nella specifica HTML, dove è descritto come “accesso denominato su Window oggetto."

Internet Explorer è stato il primo a implementare la funzionalità. Anche tutti gli altri browser lo hanno aggiunto. Gecko era l'unico browser all'epoca a non supportarlo direttamente in modalità standard, optando invece per renderlo una funzionalità sperimentale. C'era esitazione a implementarlo a tutti, ma esso è andato avanti in nome della compatibilità del browser (Ci ha anche provato Gecko convincere WebKit per spostarlo fuori dalla modalità standard) e alla fine è arrivato alla modalità standard in Firefox 14.

Una cosa che potrebbe non essere ben nota è che i browser hanno dovuto mettere in atto alcune misure precauzionali, con vari gradi di successo, per garantire che i globali generati non rompano la pagina web. Una di queste misure è...

Ombreggiatura variabile

Probabilmente la parte più interessante di questa funzione è che i riferimenti agli elementi denominati non lo fanno ombreggiare le variabili globali esistenti. Quindi, se un elemento DOM ha un id che è già definito come globale, non sovrascriverà quello esistente. Per esempio:


  
    window.foo = "bar";
  


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

Ed è vero anche il contrario:

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

Questo comportamento è essenziale perché annulla le sostituzioni pericolose come

, che altrimenti creerebbe un conflitto invalidando il alert API. Questa tecnica di salvaguardia potrebbe benissimo essere il motivo per cui tu, se sei come me, lo stai imparando per la prima volta.

Il caso contro i global nominati

In precedenza, ho detto che l'utilizzo di elementi denominati globali come riferimenti potrebbe non essere l'idea migliore. Ci sono molte ragioni per questo, quali TJ VanToll ha parlato bene del suo blog e riassumo qui:

  • Se il DOM cambia, cambia anche il riferimento. Ciò rende alcuni davvero "fragili" (il termine della specifica per esso) codice in cui la separazione delle preoccupazioni tra HTML e JavaScript potrebbe essere eccessiva.
  • I riferimenti accidentali sono fin troppo facili. Un semplice errore di battitura potrebbe benissimo finire per fare riferimento a un globale denominato e darti risultati inaspettati.
  • È implementato in modo diverso nei browser. Ad esempio, dovremmo essere in grado di accedere a un'ancora con un id - per esempio — ma alcuni browser (in particolare Safari e Firefox) restituiscono a ReferenceError nella consolle.
  • Potrebbe non restituire ciò che pensi. Secondo le specifiche, quando ci sono più istanze dello stesso elemento con nome nel DOM, diciamo due istanze di

    — il browser dovrebbe restituire un HTMLCollection con un array di istanze. Firefox, tuttavia, restituisce solo la prima istanza. Poi ancora, la specifica dice dovremmo usare un'istanza di an id comunque nell'albero di un elemento. Ma ciò non impedirà a una pagina di funzionare o qualcosa del genere.

  • Forse c'è un costo di prestazione? Voglio dire, il browser deve fare quell'elenco di riferimenti e mantenerlo. Un paio di persone hanno eseguito dei test in questo thread StackOverflow, dove si trovavano in realtà i globali denominati più performante in un test ed meno performante in un test più recente.

Ulteriori considerazioni

Diciamo che abbandoniamo le critiche contro l'utilizzo di globali denominati e li usiamo comunque. Va tutto bene. Ma ci sono alcune cose che potresti voler considerare mentre fai.

Polyfill

Per quanto possa sembrare strano, questi tipi di controlli globali sono un tipico requisito di configurazione per i polyfill. Dai un'occhiata al seguente esempio in cui impostiamo un cookie utilizzando il nuovo CookieStore API, compilandolo su browser che non lo supportano ancora:


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

Questo codice funziona perfettamente in Chrome, ma genera il seguente errore in Safari.:

TypeError: cookieStore.set is not a function

Safari non supporta il CookieStore API al momento della stesura di questo documento. Di conseguenza, il polyfill non viene applicato perché il img ID elemento crea una variabile globale che si scontra con il cookieStore globale.

Aggiornamenti dell'API JavaScript

Possiamo capovolgere la situazione e trovare un altro problema in cui gli aggiornamenti al motore JavaScript del browser possono interrompere i riferimenti globali di un elemento denominato.

Per esempio:


  
  
    window.BarcodeDetector.focus();
  

Quello script cattura un riferimento all'elemento di input e lo invoca focus() su di esso. Funziona correttamente. Ancora, non sappiamo come lungo continuerà a funzionare.

Vedi, la variabile globale che stiamo usando per fare riferimento all'elemento di input smetterà di funzionare non appena i browser inizieranno a supportare il BarcodeDetector API. A quel punto, il window.BarcodeDetector global non sarà più un riferimento all'elemento di input e .focus() lancerà un "window.BarcodeDetector.focus non è una funzione” errore.

Bonus: non tutti gli elementi denominati generano riferimenti globali

Vuoi sentire qualcosa di divertente? Per aggiungere la beffa al danno, gli elementi denominati sono accessibili come variabili globali solo se i nomi non contengono altro che lettere. I browser non creeranno un riferimento globale per un elemento con un ID che contiene caratteri e numeri speciali, ad esempio hello-world ed item1.

Conclusione

Riassumiamo come siamo arrivati ​​qui:

  • Tutti i principali browser creano automaticamente riferimenti globali a ciascun elemento DOM con un id (o, in alcuni casi, a name attributo).
  • L'accesso a questi elementi attraverso i loro riferimenti globali è inaffidabile e potenzialmente pericoloso. Uso querySelector or getElementById anziché.
  • Poiché i riferimenti globali vengono generati automaticamente, potrebbero avere alcuni effetti collaterali sul codice. Questo è un buon motivo per evitare di usare il id attributo a meno che tu non ne abbia davvero bisogno.

Alla fine della giornata, è probabilmente una buona idea evitare di utilizzare globali denominati in JavaScript. Ho citato in precedenza le specifiche su come porta al codice "fragile", ma ecco il testo completo per portare a casa il punto:

Come regola generale, fare affidamento su questo porterà a un codice fragile. Quali ID finiscono per essere mappati su questa API possono variare nel tempo, poiché, ad esempio, vengono aggiunte nuove funzionalità alla piattaforma web. Invece di questo, usa document.getElementById() or document.querySelector().

Penso che il fatto che le stesse specifiche HTML raccomandino di stare lontano da questa funzione parli da sé.

Timestamp:

Di più da Trucchi CSS