Solía JSLint en un archivo JavaScript mío. Lanzó el error:
for( ind in evtListeners ) {
Problema en la línea 41, carácter 9: El cuerpo de un for in debe estar envuelto en una declaración if para filtrar las propiedades no deseadas del prototipo.
¿Qué significa esto?
javascript
jslint
jrharshath
fuente
fuente
if (evtListeners.hasOwnProperty(ind))
para restringir el procesamiento solo a las propiedades propias (no heredadas). Aún así, en algunos casos realmente desea iterar sobre todas las propiedades, incluidas las heredadas. En ese caso, JSLint lo obliga a ajustar el cuerpo del bucle en una declaración if para decidir qué propiedades realmente desea. Esto funcionará y hará feliz a JSlint:if (evtListeners[ind] !== undefined)
Respuestas:
En primer lugar, nunca use un
for in
bucle para enumerar sobre una matriz. Nunca. Usa lo bueno de siemprefor(var i = 0; i<arr.length; i++)
.La razón detrás de esto es la siguiente: cada objeto en JavaScript tiene un campo especial llamado
prototype
. Todo lo que agregue a ese campo será accesible en cada objeto de ese tipo. Suponga que desea que todas las matrices tengan una nueva función genial llamadafilter_0
que filtre los ceros.Esta es una forma estándar de extender objetos y agregar nuevos métodos. Muchas bibliotecas hacen esto. Sin embargo, veamos cómo
for in
funciona ahora:¿Lo ves? De repente piensa que filter_0 es otro índice de matriz. Por supuesto, no es realmente un índice numérico, sino que se
for in
enumera a través de campos de objeto, no solo índices numéricos. Así que ahora estamos enumerando a través de cada índice numérico yfilter_0
. Perofilter_0
no es un campo de ningún objeto de matriz en particular, cada objeto de matriz tiene esta propiedad ahora.Afortunadamente, todos los objetos tienen un
hasOwnProperty
método que comprueba si este campo realmente pertenece al objeto en sí o si simplemente se hereda de la cadena de prototipos y, por lo tanto, pertenece a todos los objetos de ese tipo.Tenga en cuenta que, aunque este código funciona como se espera para las matrices, nunca, nunca , debe usar
for in
yfor each in
para las matrices. Recuerde quefor in
enumera los campos de un objeto, no los índices o valores de la matriz.fuente
for in
para iterar sobre matrices porque el lenguaje no asigna un orden en el quefor in
se enumerará sobre una matriz. Puede que no esté en orden numérico. Además, si usa la construcción de estilo `for (i = 0; i <array.length; i ++), puede estar seguro de que solo está iterando índices numéricos en orden y sin propiedades alfanuméricas.for-in
bucles (que son impresionantes, por cierto), deberíamos educarlos sobre cómo funcionan (hecho correctamente en esta respuesta) y presentarlos paraObject.defineProperty()
que puedan extender sus prototipos de manera segura sin romper nada. Por cierto, no se deben hacer prototipos de objetos nativos sin ellosObject.defineProperty
.Douglas Crockford, el autor de jslint ha escrito (y hablado) sobre este tema muchas veces. Hay una sección en esta página de su sitio web que cubre esto:
Crockford también tiene una serie de videos sobre el teatro YUI donde habla sobre esto. La serie de videos / charlas de Crockford sobre JavaScript son de visita obligada si usted es un poco serio con respecto a JavaScript.
fuente
Malo: (jsHint arrojará un error)
Bueno:
fuente
La respuesta de Vava está en el blanco. Si usa jQuery, entonces la
$.each()
función se encarga de esto, por lo tanto, es más seguro de usar.fuente
$.each
(o underscore.js_.each
) si puede salirse con la suyafor
. jsperf tiene algunas pruebas de comparación reveladoras que vale la pena ejecutar.@todos: todo en JavaScript es un objeto (), por lo que las declaraciones como "solo usar esto en objetos" son un poco engañosas. Además, JavaScript no está fuertemente tipado para que 1 == "1" sea verdadero (aunque 1 === "1" no lo es, Crockford es grande en esto). Cuando se trata del concepto progromático de matrices en JS, la tipificación es importante en la definición.
@Brenton: no es necesario ser un dictador de terminología; "matriz asociativa", "diccionario", "hash", "objeto", todos estos conceptos de programación se aplican a una estructura en JS. Son pares de valores de nombre (clave, índice), donde el valor puede ser cualquier otro objeto (las cadenas también son objetos)
Entonces,
new Array()
es lo mismo que[]
new Object()
es más o menos similar a{}
Crea una estructura que es una matriz con la restricción de que todos los índices (también conocidos como claves) deben ser un número entero. También permite la asignación automática de nuevos índices a través de .push ()
De hecho, se trata mejor a través de
for(initialization;condition;update){
Pero que pasa:
Prueba esto:
Quizás no sea el mejor uso de una matriz, sino solo una ilustración de que las cosas no siempre son claras.
Si conoce sus claves, y definitivamente si no son números enteros, su única opción de estructura como matriz es el objeto.
fuente
Seguramente es un poco extremo decir
?
Vale la pena resaltar la sección en el extracto de Douglas Crockford
Si necesita una matriz asociativa (también conocida como tabla hash / diccionario) donde se nombran las claves en lugar de indexarse numéricamente, deberá implementar esto como un objeto, por ejemplo
var myAssocArray = {key1: "value1", key2: "value2"...};
.En este caso
myAssocArray.length
, aparecerá nulo (porque este objeto no tiene una propiedad de 'longitud'), yi < myAssocArray.length
no lo llevará muy lejos. Además de proporcionar una mayor comodidad, esperaría que las matrices asociativas ofrezcan ventajas de rendimiento en muchas situaciones, ya que las claves de la matriz pueden ser propiedades útiles (es decir, la propiedad o el nombre de identificación de un miembro de la matriz), lo que significa que no tiene que iterar a través de un largo matriz evaluando repetidamente si las declaraciones encuentran la entrada de matriz que está buscando.De todos modos, gracias también por la explicación de los mensajes de error de JSLint, ¡usaré la verificación 'isOwnProperty' ahora cuando intente a través de mis innumerables matrices asociativas!
fuente
length
propiedad, pero puede hacerlo de otra manera:var myArr = []; myArr['key1'] = 'hello'; myArr['key2'] = 'world';
var myArr = []
, debe servar myArr = {}
en PHP, son lo mismo, pero no en JS.Esto significa que debe filtrar las propiedades de evtListeners con el método hasOwnProperty .
fuente
Solo para agregar al tema de for in / for / $. Each, agregué un caso de prueba jsperf para usar $ .each vs for in: http://jsperf.com/each-vs-for-in/2
Diferentes navegadores / versiones lo manejan de manera diferente, pero parece que $ .each y directamente son las opciones más baratas en términos de rendimiento.
Si está utilizando for in para iterar a través de una matriz / objeto asociativo, sabiendo lo que busca e ignorando todo lo demás, use $ .each si usa jQuery, o solo for in (y luego un descanso; una vez que haya alcanzó lo que sabe que debería ser el último elemento)
Si está iterando a través de una matriz para realizar algo con cada par de claves, debe usar el método hasOwnProperty si NO usa jQuery y usar $ .each si SÍ usa jQuery.
Sin
for(i=0;i<o.length;i++)
embargo, siempre use si no necesita una matriz asociativa ... lol chrome realizó eso un 97% más rápido que un for in o$.each
fuente