Por que estender os protótipos do objeto DOM / built-in é uma má ideia?

15

Estou à procura de uma resposta definitiva para o motivo pelo qual a extensão de protótipos incorporados é tão castigada na comunidade de desenvolvedores JS. Eu tenho usado o framework Prototype JS por um tempo, e para mim fazer [1,2,3].each(doStuff) parece muito mais elegante que $.each([1,2,3], doStuff) . Eu sei que isso cria "poluição de namespace", mas eu ainda não entendo porque isso é considerado uma coisa ruim. Também há alguma degradação real do desempenho associada à ampliação de protótipos internos? Obrigado!

    
por lxe 16.05.2011 / 23:03
fonte

5 respostas

12

Eu sugiro que você leia este artigo que, na minha opinião, explica muito bem por que estender objetos é uma má idéia, no que diz respeito ao Prototype também.

Em resumo:

Falta de especificação

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.

Os objetos de host não têm regras

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.

Possibilidade de colisões

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.

Sobrecarga de desempenho

[...] 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.

O IE DOM é uma bagunça

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

Bônus: erros no navegador

    
por 29.08.2011 / 11:14
fonte
9

Outro motivo é a legibilidade / manutenção do código. Se outro desenvolvedor (especialmente um novato) está lendo meu código e vê [0, 1, 2].foo(...) , eles podem não saber o que é o método foo ou onde encontrar documentação / fonte para ele. O foo é uma extensão para a linguagem adicionada pelo prototype.js, ou por outra biblioteca em uso, ou por alguma outra parte do meu código em outro arquivo, ou é um método JavaScript nativo que eles não conheciam? Eles precisam caçá-lo e podem não encontrá-lo imediatamente (ou se houver conflitos, eles podem não encontrar o caminho certo).

Com a abordagem jQuery, se você vir $.foo(...) , o namespace do método foo torna óbvio onde encontrar sua definição / documentação se você não souber o que faz.

    
por 29.08.2011 / 12:25
fonte
4

Aqui está o problema básico: O que acontece se você tiver duas ferramentas que estendam protótipos de maneiras incompatíveis, ou que estendam métodos comumente chamados de maneiras que produzam resultados diferentes (esse é um problema específico para for...in em JavaScript) , causando código que depende de seu comportamento normal para quebrar?

Basicamente, são os mesmos problemas que você tem quando usa mal as variáveis globais. Por si só, talvez nada de ruim aconteça. Mas, isso te deixa em apuros quando dois pedaços de código ostensivamente separados repentinamente pisam um no outro (e é uma dificuldade para depurar quando isso acontece).

Certamente o prototype.js é bem conhecido e a maioria das ferramentas funciona em torno do que ele faz. Da mesma forma, tenho certeza de que há casos em que estender protótipos de base é a coisa certa a fazer. Mas é algo para abordar com cautela.

    
por 16.05.2011 / 23:07
fonte
1

Não tenho certeza se isso realmente é um problema, mas minha experiência com versões anteriores do Internet Explorer é que às vezes nem era possível estender certos tipos de recursos.

    
por 16.05.2011 / 23:39
fonte
1

Existem dois problemas separados aqui. A primeira é a extensão geral de protótipos integrados e a outra é a extensão específica de protótipos de DOM. Os argumentos contra a extensão de protótipos integrados:

  • Conflitos potenciais: dois pedaços de código de origens diferentes, ambos definindo a mesma propriedade no mesmo protótipo
  • Efeitos colaterais: estender Array.prototype ou Object.prototype pode ter efeitos indiretos, como adicionar os métodos de extensão que estão sendo enumerados em for...in loop

Quanto à extensão de protótipos DOM, o argumento de conflito potencial acima ainda se aplica. Além disso, nós DOM são objetos de host e, como tal, não estão sujeitos a nenhuma das regras normais de objetos JavaScript nativos. Eles podem essencialmente fazer o que gostam e não têm obrigação de fornecer objetos protótipos sensatos ou mesmo permitir propriedades extras ("expando"). O IE, em particular, exerce esse direito, não fornecendo protótipos para objetos DOM antes do IE 9 e tendo várias estranhezas sobre propriedades em vários objetos DOM (embora você esteja geralmente OK atribuindo propriedades a elementos, desde que nada esteja definido document.expando to false .)

    
por 17.05.2011 / 01:13
fonte