recorrer - manejo de array con javascript
agregando funciones personalizadas en Array.prototype (5)
En general, jugar con los objetos JavaScript centrales es una mala idea. Nunca se sabe lo que las bibliotecas de terceros pueden esperar y cambiar los objetos centrales en javascript los cambia para todo.
Si usas Prototype, es especialmente malo porque el prototipo también entra en conflicto con el alcance global y es difícil saber si vas a chocar o no. En realidad, modificar las partes centrales de cualquier idioma suele ser una mala idea, incluso en javascript.
(Lisp podría ser la pequeña excepción allí)
Estaba trabajando en una aplicación asp.net habilitada para AJAX. Acabo de agregar algunos métodos a Array.prototype like
Array.prototype.doSomething = function(){
...
}
Esta solución funcionó para mí, siendo posible el código de reutilización de una manera "bonita".
Pero cuando lo probé trabajando con toda la página, tuve problemas ... Teníamos algunos extensores de ajax personalizados, y comenzaron a comportarse como algo inesperado: algunos controles mostraban ''indefinido'' en torno a su contenido o valor.
¿Cuál podría ser la causa de eso? ¿Me falta algo sobre modificar el prototipo de objetos estándar?
Nota: estoy bastante seguro de que el error comienza cuando modifico el prototipo para Matriz. Debería ser solo compatible con IE.
Hay una advertencia! Tal vez lo hiciste: violín demo
Digamos una matriz y un método foo que devuelven el primer elemento:
var myArray = ["apple","ball","cat"];
foo(myArray) // <- ''apple''
function foo(array){
return array[0]
}
Lo anterior está bien porque las funciones se elevan a la parte superior durante el tiempo de interpretación.
Pero esto NO funciona: (Debido a que el prototipo no está definido)
myArray.foo() // <- ''undefined function foo''
Array.prototype.foo = function(){
return this[0]
}
Para que esto funcione, simplemente defina prototipos en la parte superior:
Array.prototype.foo = function(){
return this[0]
}
myArray.foo() // <- ''apple''
¡Y si! ¡Puedes anular prototipos! Está permitido. Incluso puede definir su propio método de
add
para Arrays.
La modificación de los prototipos de objetos incorporados puede ser una mala idea en general, ya que siempre tiene el potencial de entrar en conflicto con otros códigos en la misma página.
En el caso del prototipo de objeto Array, es una idea especialmente mala, porque tiene el potencial de interferir con cualquier parte del código que itere sobre los miembros de cualquier matriz, por ejemplo con for .. in
.
Para ilustrar usando un ejemplo (tomado de here ):
Array.prototype.foo = 1;
// somewhere deep in other javascript code...
var a = [1,2,3,4,5];
for (x in a){
// Now foo is a part of EVERY array and
// will show up here as a value of ''x''
}
Sería mejor para usted crear su propio tipo de constructor de objetos completo con la función doSomething, en lugar de extender la Matriz incorporada.
Editar: para repetir lo que puse en un comentario:
Lo contrario es cierto: debe evitar for..in en caso de que n00b haya modificado el prototipo de Array, y debe evitar modificar el prototipo de Array en caso de que algún n00b lo haya utilizado para .in en una matriz. ;)
Además, ahora existe Object.defineProperty
como una forma general de extender prototipos de objetos sin que las nuevas propiedades sean enumerables, aunque aún no usaría esto como justificación para extender los tipos incorporados , porque incluso además de for..in
hay aún existe la posibilidad de otros conflictos con otros scripts. Considere a alguien bifurcando su código y luego poniendo ambas versiones en la misma página: ¿su mejora personalizada del objeto Array seguirá funcionando como usted espera?
Si bien el riesgo de chocar con otras partes del código es superior a una función en un prototipo, sigue siendo un riesgo, si desea hacer esto con versiones modernas de JavaScript, puede usar el método Object.defineProperty, desactivando el bit enumerable, p.ej
// functional sort
Object.defineProperty(Array.prototype, ''sortf'', {
enumerable: false,
value: function(compare) { return [].concat(this).sort(compare); }
});
Aumentó los tipos genéricos por así decirlo. Probablemente haya sobrescrito la funcionalidad de otra lib y por eso dejó de funcionar.
Supongamos que alguna lib que está utilizando extends Array con la función Array.remove (). Después de cargar lib, también agrega remove () al prototipo de Array pero con su propia funcionalidad. Cuando lib invoque su función, probablemente funcionará de forma diferente a lo esperado y romperá su ejecución ... Eso es lo que está sucediendo aquí.