2012-01-08 6 views
6

Me gustaría eliminar ciertos miembros de un objeto (por razones de argumento, aquellos cuyas claves comienzan con '_'). ¿Cuál es una manera elegante de hacer esto? La forma ingenua sería:Buena expresión idiomática para filtrar miembros de un objeto (javascript)

for (var i in obj) 
    if (i[0] === '_') 
    delete obj[i]; 

pero eso modifica el objeto subyacente durante la iteración. En Nodo al menos supongo que pude

Object.keys(obj).forEach(function (i) { if (i[0] === '_') delete obj[i]; }); 

o reiniciar la iteración cada vez que algo se elimina con un bucle anidado incómoda.

¿Hay alguna solución mejor?

EDITAR: En las pruebas de ahora, al menos en node.js, la solución ingenua en realidad parece funcionar. Ciertamente es posible que ... en (se requiera) se implemente de forma segura. ¿Nadie sabe?

+3

¿La modificación del objeto durante el bucle 'for ... in' causa un problema? No veo cómo es muy diferente a la modificación del objeto en la devolución de llamada 'forEach()', después de todo. – Pointy

+0

Supongo que 'Object.keys' toma una instantánea de las claves en el objeto. Tal vez eso no es verdad. – Grumdrig

+0

... y suponiendo que 'for (... in ...)' no toma una instantánea del objeto. – Grumdrig

Respuesta

17

No necesita preocuparse por ello. Un extracto para ECMAScript Language Specification explícitamente §12.6.4 Unidos (subrayado por mí):

La mecánica y el fin de enumerar las propiedades (paso 6.a en el primer algoritmo, 7.a paso en la segunda) es no especificado. Las propiedades del objeto que se enumera se pueden eliminar durante la enumeración. Si se elimina una propiedad que aún no se ha visitado durante la enumeración , no se visitará. Si se agregan nuevas propiedades al objeto que se enumera durante la enumeración , no se garantiza que las propiedades recién agregadas sean visitadas en la enumeración activa. No se debe visitar el nombre de una propiedad más de una vez en ninguna enumeración.

+0

-1 - "Si una propiedad que aún no ha sido visitada durante la enumeración" - Creo que ese no es el caso aquí. – thejh

+0

@thejh, luego se aplica la sentencia anterior. 'for..in' es completamente seguro para la eliminación de propiedades según el estándar. – OnTheFly

+1

+1 buena respuesta con un downvote totalmente falso –

4

por qué no crear una lista de los nombres de eliminar como

var l = []; 
for (var i in obj) 
    if (i[0] === '_') 
    l.push(i); 
l.forEach(function(v){ delete obj[v]; }); 
4
Object.keys(obj).filter(function (v) { 
    return v[0] === "_"; 
}).forEach(function (v) { 
    delete obj[v]; 
}); 

Esto modificará el objeto durante un bucle sin embargo; p

Si utiliza más de una vez el medicamento genérico :

Object.keys(obj).filter(function (v) { 
    //filter the object values/keys by some conditions 
}).forEach(del.bind(obj)); 

function del (v) { 
    delete this[v]; 
} 
+0

Gracias. No sabía sobre 'filtro'. – Grumdrig

2

Una alternativa es crear una función devolviendo un objeto filtrado. Preferiría esta solución para evitar efectos colaterales en otras partes del código que contienen una referencia al objeto que se está modificando.

function filterObject(obj) { 
    var filtered = new Object(); 
    for (var i in obj) 
    if (i[0] != '_') 
     filtered[i] = obj[i]; 
    return filtered; 
} 
Cuestiones relacionadas