2012-01-08 13 views
6

mi piacerebbe per rimuovere alcuni membri di un oggetto (per amor di discussione, quelli le cui chiavi iniziare con '_'). Qual è un modo elegante per farlo? Il modo ingenuo sarebbe:buon linguaggio per filtrare i membri di un oggetto (Javascript)

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

ma che modifica l'oggetto sottostante durante l'iterazione. Nel nodo almeno Credo che avrei potuto

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

o riavviare l'iterazione ogni volta che qualcosa viene eliminato con un ciclo nidificato imbarazzante.

Ci sono delle soluzioni migliori?

EDIT: Nel test solo ora, in node.js almeno, la soluzione ingenua sembra davvero funzionare. È certamente possibile che per ... in (deve essere) essere implementato in sicurezza. Qualcuno sa?

+3

La modifica dell'oggetto durante il ciclo 'for ... in' causa un problema? Non vedo come sia molto diverso da modificare l'oggetto nella callback 'forEach()', dopo tutto. – Pointy

+0

sto presumendo che 'Object.keys' prende un'istantanea delle chiavi nell'oggetto. Forse non è vero. – Grumdrig

+0

... e presumendo che 'for (... in ...)' non catturi un'istantanea dell'oggetto. – Grumdrig

risposta

17

Non devi preoccuparti. Un estratto per ECMAScript Language Specification §12.6.4 esplicitamente Uniti (sottolineato da me):

La meccanica e l'ordine di enumerazione delle proprietà (punto 6.a nella primo algoritmo, 7.a passo nel secondo) è non specificato. proprietà dell'oggetto essere elencati possono essere cancellati durante l'enumerazione. Se una proprietà che non è stata ancora visitata durante l'enumerazione viene cancellata, non verrà visitata. Se le nuove proprietà vengono aggiunte all'oggetto che viene enumerato durante l'enumerazione , non è garantito che le nuove proprietà aggiunte siano visitate nell'enumerazione attiva. Il nome di una proprietà non deve essere visitato più di una volta in qualsiasi enumerazione.

+0

-1 - "Se una proprietà che non è ancora stata visitata durante l'enumerazione" - Penso che non sia il caso qui. – thejh

+0

@thejh, quindi si applica la frase precedente. 'for..in' è completamente sicuro per la cancellazione di proprietà come da standard. – OnTheFly

+1

+1 buona risposta con un downvote totalmente falso –

4

perché non creare un elenco dei nomi da rimuovere come

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]; 
}); 

Questo modificherà l'oggetto nel corso di un ciclo anche se, p

Se si utilizza più di una volta il generico è :

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

Grazie. Non sapevo su 'filtro'. – Grumdrig

2

Un'alternativa è creare una funzione che restituisce un oggetto filtrato. Preferirei questa soluzione per evitare effetti collaterali su altre parti del codice che contengono un riferimento all'oggetto da modificare.

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