¿Por qué es una mala idea extender los prototipos DOM / objeto incorporado?

15

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

lxe
fuente
1
Una cosa es que los for(var ... in ...)bucles se estropean ya que las funciones prototipo también se pasan.
pimvdb
44
"muy castigado", ¿en serio? Dios mío, hombre:] ¿estás bien?
pixelbobby

Respuestas:

12

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

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 totalmente al DOM Nivel 2, no es necesario exponer esos objetos globales Nodo, Elemento, HTMLElement, etc.

Los objetos 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 puede comportarse de manera impredecible y completamente errática.

Posibilidad de colisiones

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

Cada control de forma con nombre sombrea las propiedades heredadas a través de la cadena de prototipo. La posibilidad de colisiones y errores inesperados en los elementos de formulario es aún mayor.

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

Sobrecarga de rendimiento

[...] los navegadores que no admiten extensiones de elementos, como IE 6, 7, Safari 2.x, etc., requieren la extensión manual de objetos. El problema es que la extensión manual es lenta, inconveniente y no escala.

[...] una vez que comienza a extender elementos, la API de biblioteca probablemente necesite devolver elementos extendidos a todas partes. Como resultado, los métodos de consulta como $$ podrían terminar extendiendo cada elemento en una consulta.

IE DOM es un desastre

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

Bonus: errores del navegador

Jose Faeti
fuente
9

Otra razón es la legibilidad / mantenibilidad del código. Si otro desarrollador (especialmente un novato) está leyendo mi código y ve [0, 1, 2].foo(...), es posible que no sepan cuál es el método foo o dónde encontrar documentación / fuente. ¿Es foo 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 nativo de JavaScript que no sabían? Necesitan buscarlo y es posible que no lo encuentren de inmediato (o si hay conflictos, es posible que no encuentren el correcto).

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

Bruce Harris
fuente
La capacidad de descubrir de dónde provienen los métodos es muy importante para los lectores. Aunque realmente no creo que jQuery sea un buen ejemplo, ya que el signo del dólar es un desafío de búsqueda cuando saltas a leer código web y aún no sabes lo que es.
Simon Feltman
4

Aquí está el problema básico: qué sucede si tiene dos herramientas que extienden prototipos de manera incompatible, o que extienden métodos comúnmente llamados de manera tal que producen resultados diferentes (este es un problema particular para for...inJavaScript), causando código que depende en su comportamiento normal para romper?

Básicamente, son los mismos problemas que tiene cuando usa mal las variables globales. Por sí mismo, tal vez no pase nada malo. Pero, te abre problemas cuando dos partes de código aparentemente separadas se pisan repentinamente (y es una tarea difícil de depurar cuando eso sucede).

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


fuente
1

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


fuente
1

Hay dos problemas separados aquí. El primero es la extensión general de los prototipos incorporados, y el otro es específicamente extender los prototipos DOM. Los argumentos en contra de extender los 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.prototypeo Object.prototypepuede tener efectos secundarios, como agregar los métodos de extensión que se enumeran en un for...inbucle

En cuanto a la extensión de los prototipos DOM, el argumento de conflicto potencial anterior aún 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 quieran y no tienen la obligación de proporcionar objetos prototipo sensibles o incluso permitir propiedades adicionales ("expando"). IE en ejercicios particulares de este derecho, siempre y cuando no prototipos de objetos DOM antes de IE 9 y que tiene varios weirdnesses acerca de las propiedades de varios objetos DOM (aunque estás propiedades Asignación general OK a elementos, siempre conjunto de nada document.expandoa false.)

Tim Down
fuente