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

15

Sto cercando una risposta definitiva al perché estendere i prototipi integrati sia così pesantemente castigato nella comunità degli sviluppatori di JS. Sto usando il framework Prototype JS per un po ', e per me fare [1,2,3].each(doStuff) sembra molto più elegante di $.each([1,2,3], doStuff) . So che crea "inquinamento da spazio dei nomi", ma non capisco perché sia considerato una cosa negativa. Esiste anche un reale peggioramento delle prestazioni associato all'estensione dei prototipi integrati? Grazie!

    
posta lxe 16.05.2011 - 23:03
fonte

5 risposte

12

Ti suggerisco di leggere questo articolo che penso spieghi piuttosto bene perché estendere gli oggetti è una cattiva idea, anche per quanto riguarda Prototype.

In breve:

Mancanza di specifiche

Exposure of "prototype objects" is not part of any specification. [...] In order for implementation to conform to DOM Level 2 fully, there's no need to expose those global Node, Element, HTMLElement, etc. objects.

Gli oggetti host non hanno regole

DOM objects are host objects [...] Host objects may implement these internal methods with any implementation-dependent behaviour, or it may be that a host object implements only some internal methods and not others.

[...] Internal methods behavior is implementation-dependent. [...] By definition, you are working with something that's allowed to behave in unpredictable and completely erratic way.

Possibilità di collisioni

Given huge amount of environments in use today, it becomes impossible to tell if certain property is not already part of some DOM. [...]

Every named form control shadows properties inherited through prototype chain. The chance of collisions and unexpected errors on form elements is even higher.

Employing some kind of prefixing strategy can alleviate the problem. But will probably also bring extra noise.

Carico delle prestazioni

[...] browsers that don’t support element extensions—like IE 6, 7, Safari 2.x, etc.—require manual object extension. The problem is that manual extension is slow, inconvenient and doesn’t scale.

[...] once you start extending elements, library API most likely needs to return extended elements everywhere. As a result, querying methods like $$ could end up extending every single element in a query.

IE DOM è un pasticcio

As shown in previous section, manual DOM extension is a mess. But manual DOM extension in IE is even worse [...]

Bonus: bug del browser

    
risposta data 29.08.2011 - 11:14
fonte
9

Un altro motivo è la leggibilità / manutenibilità del codice. Se un altro sviluppatore (specialmente un principiante) sta leggendo il mio codice e vede [0, 1, 2].foo(...) , potrebbe 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 subito (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.

    
risposta data 29.08.2011 - 12:25
fonte
4

Ecco il problema di base: che cosa succede se hai 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...in in JavaScript) , causando così la rottura di un codice che si basa sul loro comportamento normale?

Fondamentalmente, si tratta degli stessi problemi che si verificano quando si utilizzano erroneamente variabili globali. Di per sé, forse non succede niente di male. Ma ti apre per problemi quando due pezzi di codice apparentemente separati si accavallano improvvisamente l'un l'altro (ed è un problema eseguire il debug quando ciò accade).

Certamente prototype.js è piuttosto noto e la maggior parte degli strumenti funziona su quello che fa. Allo stesso modo, sono sicuro che ci sono casi in cui estendere i prototipi di base è la cosa giusta da fare. Ma, è qualcosa da approcciare con cautela.

    
risposta data 16.05.2011 - 23:07
fonte
1

Non sono sicuro che sia 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.

    
risposta data 16.05.2011 - 23:39
fonte
1

Qui ci sono due problemi separati. Il primo è l'estensione generale dei prototipi incorporati e l'altro estende specificamente i prototipi DOM. Gli argomenti contro l'estensione dei prototipi incorporati:

  • Potenziali scontri: due pezzi di codice provenienti da fonti diverse che definiscono la stessa proprietà sullo stesso prototipo
  • Effetti collaterali: l'estensione di Array.prototype o Object.prototype può avere effetti a catena, come l'aggiunta dei metodi di estensione che vengono enumerati in un ciclo for...in

Per quanto riguarda l'estensione dei prototipi DOM, il potenziale argomento di conflitto sopra si applica ancora. Inoltre, i nodi DOM sono oggetti host e come tali non sono soggetti a nessuna delle normali regole degli oggetti JavaScript nativi. Possono essenzialmente fare ciò che vogliono e non sono obbligati a fornire oggetti prototipo sensibili o addirittura a consentire proprietà extra ("expando"). In particolare, IE esercita questo diritto, non fornendo prototipi per gli oggetti DOM prima di IE 9 e con varie stranezze sulle proprietà su vari oggetti DOM (sebbene in genere si assegni le proprietà agli elementi, a condizione che non sia impostato document.expando su false .)

    
risposta data 17.05.2011 - 01:13
fonte

Leggi altre domande sui tag