Gli elementi dell’albero DOM con ID diventano variabili globali?

Lavorando su un’idea per un semplice wrapper HTMLElement mi sono imbattuto in quanto segue per Internet Explorer e Chrome :

Per un determinato HTMLElement con ID nell’albero DOM, è ansible recuperare il div utilizzando il suo ID come nome della variabile. Quindi per un div come

some text

in Internet Explorer 8 e Chrome puoi fare:

 alert(example.innerHTML); //=> 'some text' 

o

 alert(window['example'].innerHTML); //=> 'some text' 

Quindi, questo significa che ogni elemento dell’albero DOM viene convertito in una variabile nello spazio dei nomi globale? E significa anche che uno può usare questo come sostituto del metodo getElementById in questi browser?

Ciò che dovrebbe accadere è che gli “elementi nominati” vengono aggiunti come proprietà apparenti dell’object del document . Questa è una pessima idea, in quanto consente ai nomi di elementi di scontrarsi con le proprietà reali del document .

IE ha peggiorato la situazione aggiungendo anche elementi denominati come proprietà dell’object window . Questo è doppiamente cattivo in quanto ora devi evitare di nominare i tuoi elementi dopo che un membro del document o dell’object della window tu (o qualsiasi altro codice di libreria nel tuo progetto) potrebbero voler usare.

Significa anche che questi elementi sono visibili come variabili globali. Fortunatamente in questo caso qualsiasi vera dichiarazione globale di variabili o function nel tuo codice li ombreggia, quindi non devi preoccuparti tanto di nominare qui, ma se provi a fare un assegnamento a una variabile globale con un nome a contrasto e ti dimentichi per dichiararlo var , riceverai un errore in IE nel tentativo di assegnare il valore all’elemento stesso.

Generalmente è considerata una ctriggers pratica omettere var , oltre a fare affidamento su elementi denominati visibili sulla window o globali. Attenersi a document.getElementById , che è più ampiamente supportato e meno ambiguo. Puoi scrivere una funzione di wrapper banale con un nome più breve se non ti piace la digitazione. In ogni caso, non ha senso usare una cache di ricerca id-to-element, perché i browser in genere ottimizzano la chiamata getElementById per utilizzare comunque una ricerca rapida; tutto ciò che ottieni sono problemi quando gli elementi cambiano id o vengono aggiunti / rimossi dal documento.

Opera ha copiato IE, quindi WebKit si è unito, e ora sia la pratica precedentemente non standardizzata di mettere gli elementi denominati sulle proprietà del document , sia la pratica precedente di IE di metterli in una window viene standardizzata da HTML5, il cui approccio è quello di documentare e standardizzare ogni pratica terribile che ci viene inflitta dagli autori del browser, rendendoli parte del web per sempre. Quindi anche Firefox 4 supporterà questo.

Cosa sono gli “elementi nominati”? Qualsiasi cosa con un id e qualsiasi cosa con un name utilizzato per scopi “identificativi”: vale a dire, forms, immagini, ancore e poche altre, ma non altre istanze non correlate di un attributo name , come i nomi di controllo nei campi di input del modulo, i nomi dei parametri in o il tipo di metadati in . I name “identificazione” sono quelli che dovrebbero essere evitati a favore id .

Come menzionato nella risposta precedente, questo comportamento è noto come accesso con nome sull’object finestra . Il valore dell’attributo name per alcuni elementi e il valore dell’attributo id per tutti gli elementi sono resi disponibili come proprietà dell’object globale della window . Questi sono conosciuti come elementi con nome. Poiché la window è l’object globale nel browser, ogni elemento denominato sarà accessibile come variabile globale.

Questo è stato originariamente aggiunto da Internet Explorer e alla fine è stato implementato da tutti gli altri browser semplicemente per compatibilità con i siti che dipendono da questo comportamento. È interessante notare che Gecko (il motore di rendering di Firefox) ha scelto di implementarlo solo in modalità quirk , mentre altri motori di rendering lo hanno abbandonato in modalità standard.

Tuttavia, a partire da Firefox 14, Firefox ora supporta anche l’accesso con nome sull’object window in modalità standard. Perché hanno cambiato questo? Risulta che ci sono ancora molti siti che si basano su questa funzionalità in modalità standard. Microsoft ha anche rilasciato una demo di marketing che ha impedito alla demo di funzionare in Firefox.

Recentemente, Webkit ha considerato il contrario , relegando l’accesso con nome sull’object window in modalità solo quirk. L’hanno deciso contro lo stesso ragionamento di Gecko.

Quindi … pazzesco come sembra che ora questo comportamento sia tecnicamente sicuro nell’ultima versione di tutti i principali browser in modalità standard . Ma mentre l’accesso con nome può sembrare un po ‘conveniente, non dovrebbe essere usato .

Perché? Gran parte del ragionamento può essere riassunto in questo articolo sul perché le variabili globali sono cattive . In poche parole, avere un sacco di variabili globali extra porta a più bug. Diciamo che digiti accidentalmente il nome di una var e che capiti di digitare un id di un nodo DOM, SORPRESA!

Inoltre, nonostante siano standardizzati, ci sono ancora alcune discrepanze nelle implementazioni del browser di accesso con nome.

  • IE rende erroneamente il valore dell’attributo name accessibile per gli elementi del modulo (input, select, ecc.).
  • Gecko e Webkit NON fanno in modo che i tag accessibili tramite il loro attributo name .
  • Gecko gestisce erroneamente più elementi con nome con lo stesso nome (restituisce un riferimento a un singolo nodo invece di una matrice di riferimenti).

E sono sicuro che c’è di più se provi ad usare l’accesso con nome nei casi limite.

Come menzionato in altre risposte, usa document.getElementById per ottenere un riferimento a un nodo DOM tramite il suo id . Se è necessario ottenere un riferimento a un nodo tramite il relativo attributo name utilizzare document.querySelectorAll .

Per favore, ti preghiamo di non propagare questo problema usando l’accesso con nome nel tuo sito. Così tanti sviluppatori web hanno perso tempo a cercare di rintracciare questo comportamento magico . Abbiamo davvero bisogno di agire e ottenere motori di rendering per distriggersre l’accesso denominato in modalità standard. A breve termine romperà alcuni siti facendo cose cattive, ma a lungo termine aiuterà a far avanzare il web.

Se sei interessato, ne parlo più in dettaglio sul mio blog – https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/ .

Dovresti attenersi a getElementById() in questi casi, ad esempio:

 document.getElementById('example').innerHTML 

IE ama mescolare gli elementi con gli attributi di name e ID nello spazio dei nomi globale, quindi è meglio essere espliciti su ciò che stai cercando di ottenere.

Si lo fanno.

Testato su Chrome 55, Firefox 50, IE 11, IE Edge 14 e Safari 10
con il seguente esempio:

      
Hello World!

http://jsbin.com/mahobinopa/edit?html,output