Por que estender os protótipos de objetos internos DOM / é uma má idéia?


15

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


1
Uma coisa é que os for(var ... in ...)loops ficam confusos, pois as funções do protótipo também são passadas.
Pimvdb

4
"fortemente castigado", sério ?! bom Deus, cara:] você está bem?
Pixelbobby

Respostas:


12

Eu sugiro que você leia este artigo, o que eu acho que explica muito bem por que estender objetos é uma má idéia, com relação ao Prototype também.

Em suma:

Falta de especificação

A exposição de "objetos protótipos" não faz parte de nenhuma especificação. [...] Para que a implementação esteja totalmente em conformidade com o DOM Nível 2, não há necessidade de expor esses objetos globais de Nó, Elemento, HTMLElement etc.

Objetos host não têm regras

Objetos DOM são objetos [...] host Os objetos host podem implementar esses métodos internos com qualquer comportamento dependente da implementação, ou pode ser que um objeto host implemente apenas alguns métodos internos e não outros.

[...] o comportamento dos métodos internos depende da implementação. [...] Por definição, você está trabalhando com algo que pode se comportar de maneira imprevisível e completamente errática.

Possibilidade de colisões

Dada a enorme quantidade de ambientes em uso atualmente, torna-se impossível saber se determinada propriedade ainda não faz parte de algum DOM. [...]

Todo controle de formulário nomeado sombreia as propriedades herdadas pela cadeia de protótipos. A chance de colisões e erros inesperados nos elementos do formulário é ainda maior.

Empregar algum tipo de estratégia de prefixo pode aliviar o problema. Mas provavelmente também trará ruído extra.

Sobrecarga de desempenho

[...] navegadores que não suportam extensões de elementos - como IE 6, 7, Safari 2.x etc. - requerem extensão manual de objetos. O problema é que a extensão manual é lenta, inconveniente e não é escalável.

[...] depois que você começa a estender elementos, a API da biblioteca provavelmente precisa retornar elementos estendidos em todos os lugares. Como resultado, métodos de consulta como $$ podem acabar estendendo todos os elementos de uma consulta.

IE DOM está uma bagunça

Como mostrado na seção anterior, a extensão manual do DOM está uma bagunça. Mas a extensão manual do DOM no IE é ainda pior [...]

Bônus: bugs no navegador


9

Outro motivo é a legibilidade / manutenção do código. Se outro desenvolvedor (especialmente um novato) estiver lendo meu código e vir [0, 1, 2].foo(...), ele pode não saber qual é o método foo ou onde encontrar documentação / fonte para ele. Foo é uma extensão do idioma adicionada por 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 desconheciam? Eles precisam procurá-lo e podem não encontrá-lo imediatamente (ou, se houver conflitos, podem não encontrar o caminho certo).

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


A descoberta de onde os métodos vêm é muito importante para os leitores. Embora eu realmente não ache que o jQuery seja um bom exemplo, pois o cifrão é desafiador quando você pula para ler o código da web e ainda não sabe o que é.
Simon Feltman

4

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

Basicamente, são os mesmos problemas que você tem ao usar mal as variáveis ​​globais. Por si só, talvez nada de ruim aconteça. Mas isso abre problemas quando dois códigos ostensivamente separados subitamente se interagem (e é difícil debugar quando isso acontece).

Certamente prototype.js é bastante conhecido e a maioria das ferramentas trabalha em torno do que 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.


1

Não tenho certeza se isso ainda é 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 build.


1

Existem duas questões separadas aqui. O primeiro é a extensão geral de protótipos internos, e o outro é a extensão específica de protótipos DOM. Os argumentos contra a extensão de protótipos internos:

  • Conflitos em potencial: dois pedaços de código de fontes diferentes, ambos definindo a mesma propriedade no mesmo protótipo
  • Efeitos colaterais: estender Array.prototypeou Object.prototypepode ter efeitos indiretos, como adicionar os métodos de extensão que estão sendo enumerados em um for...inloop

Quanto à extensão dos protótipos do DOM, o potencial argumento de conflito acima ainda se aplica. Além disso, os 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 quiserem e não têm obrigação de fornecer objetos protótipos sensíveis ou até 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ê geralmente esteja bem atribuindo propriedades a elementos, desde que nada esteja definido document.expandocomo false).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.