¿Por qué es una mala idea extender los prototipos de objetos DOM / incorporados?

15

Estoy buscando una respuesta definitiva a por qué la extensión de prototipos incorporados está tan castigada en la comunidad de desarrolladores de JS. He estado usando el framework Prototype JS por un tiempo, y para mí, [1,2,3].each(doStuff) parece mucho más elegante que $.each([1,2,3], doStuff) . Sé que crea "contaminación de espacio de nombres", pero todavía no entiendo por qué se considera algo malo. ¿También hay una degradación real del rendimiento asociada con la extensión de los prototipos incorporados? Gracias!

    
pregunta lxe 16.05.2011 - 23:03

5 respuestas

12

Le sugiero que lea este artículo que creo que explica bastante bien por qué extender objetos Es una mala idea, con respecto a Prototype también.

En resumen:

Falta de especificación

  

La exposición de "objetos prototipo" no forma parte de ninguna especificación.   [...] Para que la implementación se ajuste plenamente al nivel 2 de DOM,   no hay necesidad de exponer esos Nodos globales, Elementos, HTMLElement,   objetos etc.

Los objetos del host no tienen reglas

  

Los objetos DOM son objetos host [...] Los objetos host pueden implementar estos   métodos internos con cualquier comportamiento dependiente de la implementación, o   Puede ser que un objeto host implemente solo algunos métodos internos y   no otros.

     

[...] El comportamiento de los métodos internos depende de la implementación. [...] Por   definición, estás trabajando con algo que está permitido comportarse en   De manera impredecible y completamente errática.

Posibilidad de colisiones

  

Dada la enorme cantidad de entornos en uso hoy en día, se vuelve imposible   para saber si cierta propiedad no es ya parte de algún DOM. [...]

     

Todas las propiedades de sombras de control de formulario con nombre heredadas a través de   Cadena prototipo. La posibilidad de colisiones y errores inesperados en   Los elementos de formulario son aún más altos.

     

Emplear algún tipo de estrategia de prefijo puede aliviar el problema.   Pero probablemente también traerá ruido adicional.

Gastos generales de rendimiento

  

[...] navegadores que no admiten extensiones de elementos, como IE 6, 7,   Safari 2.x, etc. — requiere extensión manual del objeto. El problema es ese   la extensión manual es lenta, inconveniente y no se puede escalar.

     

[...] una vez que comienzas a extender elementos, la API de la biblioteca lo más probable es que necesite   Para devolver elementos extendidos en todas partes. Como resultado, los métodos de consulta.   como $$ podría terminar extendiendo cada elemento en una consulta.

IE DOM es un desastre

  

Como se muestra en la sección anterior, la extensión manual de DOM es un desastre. Pero   la extensión manual de DOM en IE es aún peor [...]

Bono: errores del navegador

    
respondido por el Jose Faeti 29.08.2011 - 11:14
9

Otra razón es la legibilidad / mantenibilidad del código. Si otro desarrollador (especialmente un novato) está leyendo mi código y ve a [0, 1, 2].foo(...) , es posible que no sepan cuál es el método foo o dónde encontrar documentación / fuente para ello. ¿Foo es una extensión del lenguaje agregado por prototype.js, o por otra biblioteca en uso, o por alguna otra parte de mi código en otro archivo, o es un método de JavaScript nativo que no conocían? Necesitan buscarlo y es posible que no lo encuentren de inmediato (o si hay conflictos, es posible que no encuentren el adecuado).

Con el enfoque jQuery, si ves $.foo(...) , el espacio de nombres del método foo hace que sea obvio dónde encontrar su definición / documentación si no sabes lo que hace.

    
respondido por el Bruce Harris 29.08.2011 - 12:25
4

Aquí está el problema básico: ¿Qué sucede si tiene dos herramientas que extienden prototipos de formas incompatibles, o que extienden métodos comúnmente llamados de manera tal que produzcan resultados diferentes (este es un problema particular para for...in en JavaScript) , ¿causando así que el código que se basa en su comportamiento normal se rompa?

Básicamente, son los mismos problemas que tiene cuando utiliza mal las variables globales. Por sí mismo, quizás no pase nada malo. Pero, te abre para problemas cuando dos piezas de código aparentemente separadas de repente se pisan unas sobre otras (y es un dolor depurar cuando eso sucede).

Ciertamente, prototype.js es bastante conocido y la mayoría de las herramientas trabajan en torno a lo que hace. Del mismo modo, estoy seguro de que hay casos en los que extender prototipos de base es lo correcto. Pero, es algo para acercarse con precaución.

    
respondido por el Luke 16.05.2011 - 23:07
1

Ya no estoy seguro de si esto sigue siendo un problema, pero mi experiencia con las versiones anteriores de Internet Explorer es que a veces ni siquiera era posible extender ciertos tipos incorporados.

    
respondido por el Jan-Peter Vos 16.05.2011 - 23:39
1

Hay dos cuestiones separadas aquí. El primero es la extensión general de los prototipos incorporados, y el otro es la extensión específica de los prototipos DOM. Los argumentos en contra de extender prototipos incorporados:

  • Choques potenciales: dos piezas de código de diferentes fuentes que definen la misma propiedad en el mismo prototipo
  • Efectos secundarios: extender Array.prototype o Object.prototype puede tener efectos secundarios, como agregar los métodos de extensión que se enumeran en un for...in loop

En cuanto a la extensión de los prototipos DOM, el posible argumento de conflicto anterior todavía se aplica. Además, los nodos DOM son objetos host y, como tales, no están sujetos a ninguna de las reglas normales de los objetos JavaScript nativos. Básicamente, pueden hacer lo que les gusta y no tienen la obligación de proporcionar objetos prototipo razonables o incluso permitir propiedades adicionales ("expando"). IE, en particular, ejerce este derecho, no proporciona prototipos para objetos DOM antes de IE 9 y tiene varias rarezas acerca de las propiedades en varios objetos DOM (aunque generalmente está bien asignar propiedades a los elementos, siempre que no haya establecido document.expando a false ).

    
respondido por el Tim Down 17.05.2011 - 01:13

Lea otras preguntas en las etiquetas