Perché l'estensione dei prototipi di oggetti DOM / built-in è una cattiva idea?


15

Sto cercando una risposta definitiva al motivo per cui l'estensione dei prototipi integrati è così fortemente rimproverata nella comunità degli sviluppatori JS. Ho usato il framework Prototype JS per un po ', e per me farlo [1,2,3].each(doStuff)sembra molto più elegante di $.each([1,2,3], doStuff). So che crea "inquinamento dello spazio dei nomi", ma non capisco perché sia ​​considerato una cosa negativa. Esiste anche un reale degrado delle prestazioni associato all'estensione dei prototipi integrati? Grazie!


1
Una cosa è che i for(var ... in ...)loop vengono incasinati poiché vengono passate anche le funzioni del prototipo.
pimvdb,

4
"fortemente castigato", davvero ?! buon dio, amico:] stai bene?
pixelbobby,

Risposte:


12

Ti suggerisco di leggere questo articolo che, a mio avviso, spiega abbastanza bene perché l'estensione degli oggetti è una cattiva idea, anche per quanto riguarda Prototype.

In sintesi:

Mancanza di specifiche

L'esposizione di "oggetti prototipo" non fa parte di alcuna specifica. [...] Affinché l'implementazione sia pienamente conforme al DOM Level 2, non è necessario esporre quegli oggetti Nodo, Elemento, HTMLElement, ecc. Globali.

Gli oggetti host non hanno regole

Gli oggetti DOM sono oggetti host [...] Gli oggetti host possono implementare questi metodi interni con qualsiasi comportamento dipendente dall'implementazione, oppure può essere che un oggetto host implementi solo alcuni metodi interni e non altri.

[...] Il comportamento dei metodi interni dipende dall'implementazione. [...] Per definizione, stai lavorando con qualcosa a cui è permesso comportarsi in modo imprevedibile e completamente irregolare.

Possibilità di collisioni

Data l'enorme quantità di ambienti in uso oggi, diventa impossibile stabilire se determinate proprietà non fanno già parte di alcuni DOM. [...]

Ogni modulo denominato controlla le proprietà delle ombre ereditate attraverso la catena di prototipi. La possibilità di collisioni ed errori imprevisti sugli elementi del modulo è ancora maggiore.

L'uso di una sorta di strategia di prefisso può alleviare il problema. Ma probabilmente porterà anche rumore extra.

Prestazioni generali

[...] i browser che non supportano le estensioni degli elementi, come IE 6, 7, Safari 2.x, ecc., richiedono l'estensione manuale degli oggetti. Il problema è che l'estensione manuale è lenta, scomoda e non si adatta.

[...] una volta che inizi a estendere gli elementi, molto probabilmente l'API della libreria deve restituire elementi estesi ovunque. Di conseguenza, metodi di query come $$ potrebbero finire per estendere ogni singolo elemento in una query.

IE DOM è un casino

Come mostrato nella sezione precedente, l'estensione DOM manuale è un casino. Ma l'estensione DOM manuale in IE è anche peggio [...]

Bonus: bug del browser


9

Un altro motivo è la leggibilità / manutenibilità del codice. Se un altro sviluppatore (specialmente un novizio) sta leggendo il mio codice e vede [0, 1, 2].foo(...), potrebbero non sapere quale sia il metodo foo o dove trovare la documentazione / fonte per esso. Foo è un'estensione della lingua aggiunta da prototype.js, o da un'altra libreria in uso, o da qualche altra parte del mio codice in un altro file o è un metodo JavaScript nativo di cui non erano a conoscenza? Hanno bisogno di cercarlo e potrebbero non trovarlo immediatamente (o se ci sono conflitti potrebbero non trovare quello giusto).

Con l'approccio jQuery, se vedi $.foo(...), lo spazio dei nomi del metodo foo rende ovvio dove trovare la sua definizione / documentazione se non sai cosa fa.


La rilevabilità della provenienza dei metodi è molto importante per i lettori. Anche se non credo davvero che jQuery sia un buon esempio in quanto il simbolo del dollaro è una ricerca impegnativa quando passi alla lettura del codice web e non sai già di cosa si tratta.
Simon Feltman,

4

Ecco il problema di base: cosa succede se si hanno due strumenti che estendono i prototipi in modi incompatibili o che estendono i metodi comunemente chiamati in modo tale da produrre risultati diversi (questo è un problema particolare per for...inJavaScript), causando così il codice che si basa sul loro comportamento normale da rompere?

Fondamentalmente, sono gli stessi problemi che hai quando usi male le variabili globali. Di per sé, forse non succede nulla di brutto. Ma ti apre ai guai quando due pezzi apparentemente separati di codice si fanno improvvisamente uno contro l'altro (ed è una seccatura debug quando ciò accade).

Sicuramente prototype.js è piuttosto noto e la maggior parte degli strumenti aggira ciò che fa. Allo stesso modo, sono sicuro che ci sono casi in cui l'estensione dei prototipi di base è la cosa giusta da fare. Ma è qualcosa da affrontare con cautela.


1

Non sono sicuro che questo sia davvero ancora un problema, ma la mia esperienza con le versioni precedenti di Internet Explorer è che a volte non era nemmeno possibile estendere alcuni tipi di build-in.


1

Ci sono due problemi separati qui. Il primo è l'estensione generale dei prototipi incorporati e l'altro estende in modo specifico i prototipi DOM. Gli argomenti contro l'estensione dei prototipi incorporati:

  • Potenziali scontri: due parti di codice provenienti da fonti diverse che definiscono entrambe la stessa proprietà sullo stesso prototipo
  • Effetti collaterali: l'estensione Array.prototypeo Object.prototypepuò avere effetti a catena, come l'aggiunta dei metodi di estensione enumerati in un for...inciclo

Per quanto riguarda l'estensione dei prototipi DOM, si applica ancora il potenziale argomento di scontro sopra riportato. Inoltre, i nodi DOM sono oggetti host e come tali non sono soggetti a nessuna delle normali regole degli oggetti JavaScript nativi. In sostanza, possono fare ciò che vogliono e non hanno l'obbligo di fornire oggetti prototipo sensibili o addirittura consentire proprietà extra ("expando"). In particolare, IE esercita questo diritto, non fornendo prototipi per oggetti DOM prima di IE 9 e avendo varie stranezze sulle proprietà di vari oggetti DOM (anche se in genere stai bene assegnando proprietà agli elementi, purché nulla sia impostato document.expandosu false).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.