Rimuovere gli attributi vuoti da un oggetto in Javascript


Risposte:


184

Puoi scorrere l'oggetto:

var test = {
    test1 : null,
    test2 : 'somestring',
    test3 : 3,
}

function clean(obj) {
  for (var propName in obj) { 
    if (obj[propName] === null || obj[propName] === undefined) {
      delete obj[propName];
    }
  }
}

clean(test);

Se sei preoccupato che questa rimozione di proprietà non esegua la catena di proptype dell'oggetto, puoi anche:

function clean(obj) {
  var propNames = Object.getOwnPropertyNames(obj);
  for (var i = 0; i < propNames.length; i++) {
    var propName = propNames[i];
    if (obj[propName] === null || obj[propName] === undefined) {
      delete obj[propName];
    }
  }
}

Alcune note su null vs undefined:

test.test1 === null; // true
test.test1 == null; // true

test.notaprop === null; // false
test.notaprop == null; // true

test.notaprop === undefined; // true
test.notaprop == undefined; // true

2
Aggiunta una correzione rapida. La variabile "i" non dichiarata verrebbe fuori dallo scope esterno se questo frammento fosse mai usato in una funzione.
Eric Nguyen,

4
puoi semplificare da (test [i] === null || test [i] === undefined) a (test [i] == null)
jaf0

Ciao, @EricNguyen, a differenza di C e di altre lingue, javascript non ha un ambito di blocco per variabili (solo ambito di funzione), quindi la variabile i perderà sempre nell'ambito dopo il blocco di for .
Gerardo Lima,

1
@GerardoLima, sì. Stavo supponendo che questo sarebbe stato tutto racchiuso in una funzione. Quello che volevo dire (sempre che sia tutto avvolto con una funzione) è che è necessario la dichiarazione var o mi perderà anche al di fuori del campo di applicazione della funzione.
Eric Nguyen,

Questo farà anche scorrere il prototipo dell'oggetto primitivo, che nella maggior parte dei casi non è desiderato. stackoverflow.com/a/2869372/1612318
Rotareti

427

Utilizzando alcuni ES6 / ES2015 :

1) Una semplice fodera per rimuovere gli oggetti in linea senza assegnazione:

Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);

jsbin

2) Questo esempio è stato rimosso ...

3) Primo esempio scritto come funzione:

const removeEmpty = obj => {
  Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};

jsbin

4) Questa funzione utilizza ricorsione per eliminare anche elementi da oggetti nidificati:

const removeEmpty = obj => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === "object") removeEmpty(obj[key]); // recurse
    else if (obj[key] == null) delete obj[key]; // delete
  });
};

jsbin

4b) È simile a 4), ma invece di mutare direttamente l'oggetto sorgente, restituisce un nuovo oggetto.

const removeEmpty = obj => {
  const newObj = {};

  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === "object") {
      newObj[key] = removeEmpty(obj[key]); // recurse
    } else if (obj[key] != null) {
      newObj[key] = obj[key]; // copy value
    }
  });

  return newObj;
};

5) Un approccio funzionale a 4b) basato sulla risposta di @ MichaelJ.Zoidl usando filter()ereduce() . Anche questo restituisce un nuovo oggetto:

const removeEmpty = obj =>
  Object.keys(obj)
    .filter(k => obj[k] != null) // Remove undef. and null.
    .reduce(
      (newObj, k) =>
        typeof obj[k] === "object"
          ? { ...newObj, [k]: removeEmpty(obj[k]) } // Recurse.
          : { ...newObj, [k]: obj[k] }, // Copy value.
      {}
    );

jsbin

6) Come 4) ma con ES7 / 2016 Object.entries() .

const removeEmpty = (obj) => 
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === 'object') removeEmpty(val)
    else if (val == null) delete obj[key]
})

5b) Un'altra versione funzionale che utilizza la ricorsione e restituisce un nuovo oggetto con ES2019 Object.fromEntries() :

const removeEmpty = obj =>
  Object.fromEntries(
    Object.entries(obj)
      .filter(([k, v]) => v != null)
      .map(([k, v]) => (typeof v === "object" ? [k, removeEmpty(v)] : [k, v]))
  );

7) Come 4) ma in ES5 semplice :

function removeEmpty(obj) {
  Object.keys(obj).forEach(function(key) {
    if (obj[key] && typeof obj[key] === 'object') removeEmpty(obj[key])
    else if (obj[key] == null) delete obj[key]
  });
};

jsbin


3
@AugustinRiedinger Quando devo decidere tra un'interruzione di linea e un'abbreviazione, a volte scelgo l'abbreviazione se penso che l'abbreviazione sia il male minore. Il codice in 5) non è difficile da ragionare ed è una funzione che rimuove il vuoto keysda un object, quindi oe ksono ovvi. Ma immagino sia una questione di gusti.
Rotareti,

3
Prima versione con un sapore ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Neurotrasmettitore

1
Una riga, senza funzione:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm,

7
Dal momento che stiamo cercando di essere accurati, potrebbe essere bello vedere una soluzione immutabile. Questi stanno mutando l'oggetto di origine e stanno restituendo ingannevolmente l'oggetto che in realtà non è necessario perché l'oggetto è stato mutato. I principianti acquisiranno il valore dell'oggetto restituito e si chiederanno perché anche il loro oggetto sorgente sia modificato.
Mike McLin,

2
5) Non funziona con gli array (Object.keys restituirà i numeri di posizione dell'array come chiave per gli elementi). Forse altri hanno questo problema, ma ho trovato questo durante il test 5.
Eelco

95

Se stai usando lodash o underscore.js, ecco una soluzione semplice:

var obj = {name: 'John', age: null};

var compacted = _.pickBy(obj);

Funzionerà solo con lodash 4, pre lodash 4 o underscore.js, usare _.pick(obj, _.identity);


1
Brillante! Grazie! Cordiali saluti, ciò che non era ovvio per me è che potresti usarlo anche così: foo (). Then (_. PickBy); // filtrando i risultati vuoti
Maciej Gurban

29
Notare che questo non avrà il risultato desiderato se l'oggetto contiene valori falsi come 0 o stringhe vuote. Allora _.omit(obj, _.isUndefined)è meglio.
JHH,

5
@JHH _.isUndefinednon omette i null, usa _.omitBy(obj, _.isNil)per omettere entrambi undefinedenull
Lukasz Wiktor

@LukaszWiktor Corretto, la domanda è stata definita indefinita o nulla.
JHH il

88

Fodere più corte per ES6 +

Filtrare tutti i valori falsy ( "", 0, false, null, undefined)

Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})

Filtro nulle undefinedvalori:

Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})

Filtro SOLO null

Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})

Filtro SOLO undefined

Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})

Soluzioni ricorsive: filtri nulleundefined

Per gli oggetti:

const cleanEmpty = obj => Object.entries(obj)
        .map(([k,v])=>[k,v && typeof v === "object" ? cleanEmpty(v) : v])
        .reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {});

Per oggetti e matrici:

const cleanEmpty = obj => {
  if (Array.isArray(obj)) { 
    return obj
        .map(v => (v && typeof v === 'object') ? cleanEmpty(v) : v)
        .filter(v => !(v == null)); 
  } else { 
    return Object.entries(obj)
        .map(([k, v]) => [k, v && typeof v === 'object' ? cleanEmpty(v) : v])
        .reduce((a, [k, v]) => (v == null ? a : (a[k]=v, a)), {});
  } 
}

10
Questa dovrebbe essere l'unica risposta! Ognuno di questi frammenti genererà un nuovo oggetto in cui il vecchio non verrà mutato. Questo è preferibile! Una piccola nota se si utilizza solo v == nullsi verificherà contro undefinede null.
Megajin,

le cleanEmptysoluzioni ricorsive restituiranno un oggetto vuoto {}per gli oggetti Date
Emmanuel NK,

Un po 'più di leggibilità in una fodera li renderebbe fantastici !!
zardilior

39

Se qualcuno ha bisogno di una versione ricorsiva della risposta di Owen (e di Eric), eccola qui:

/**
 * Delete all null (or undefined) properties from an object.
 * Set 'recurse' to true if you also want to delete properties in nested objects.
 */
function delete_null_properties(test, recurse) {
    for (var i in test) {
        if (test[i] === null) {
            delete test[i];
        } else if (recurse && typeof test[i] === 'object') {
            delete_null_properties(test[i], recurse);
        }
    }
}

Dopo l'inizio del ciclo for, è necessario verificare che l'oggetto hasOwnPropertyutilizziif(test.hasOwnProperty(i)) { ... }
Augie Gardner,

@AugieGardner Sono curioso di sapere perché ti piacerebbe controllare questo - per favore spiegalo se ti piace. (Non impedirebbe il controllo delle proprietà ereditate?)
Wumms,

24

JSON.stringify rimuove le chiavi indefinite.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}

Questo non ha funzionato per me per un oggetto profondo, ma la risposta di Wumm sopra ha fatto.
Suman,

1
Se devi nullessere trattato come undefinedutilizzare la funzione di sostituzione, per maggiori informazioni fai riferimento a questa risposta: stackoverflow.com/questions/286141/…
Hooman Askari

Basta essere consapevoli che questo non rimuove i nullvalori. Prova: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }e poi console.log(removeUndefined(a)). La domanda riguardava undefinede nullvalori.
mayid

13

Probabilmente stai cercando la deleteparola chiave.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;

4
Questo è ciò che sta facendo sopra, anche questo lascia ancora indefinito nell'oggetto.
Josh Bedo,

10

La soluzione Lodash più semplice possibile per restituire un oggetto con i valori nulle undefinedfiltrati.

_.omitBy(obj, _.isNil)


questa è la soluzione più pulita finora!
Jee Mok,

9

È possibile utilizzare una combinazione di JSON.stringify, il relativo parametro di sostituzione, e JSON.parsetrasformarlo in un oggetto. L'uso di questo metodo significa anche che la sostituzione viene eseguita su tutte le chiavi nidificate all'interno di oggetti nidificati.

Oggetto di esempio

var exampleObject = {
  string: 'value',
  emptyString: '',
  integer: 0,
  nullValue: null,
  array: [1, 2, 3],
  object: {
    string: 'value',
    emptyString: '',
    integer: 0,
    nullValue: null,
    array: [1, 2, 3]
  },
  arrayOfObjects: [
    {
      string: 'value',
      emptyString: '',
      integer: 0,
      nullValue: null,
      array: [1, 2, 3]
    },
    {
      string: 'value',
      emptyString: '',
      integer: 0,
      nullValue: null,
      array: [1, 2, 3]
    }
  ]
};

Funzione di sostituzione

function replaceUndefinedOrNull(key, value) {
  if (value === null || value === undefined) {
    return undefined;
  }

  return value;
}

Pulisci l'oggetto

exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);

Esempio di CodePen


6

Utilizzando Ramda # pickBy verrà rimosso tutto null, undefinede falsevalori:

const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)

Come ha sottolineato @manroe, per mantenere i falsevalori usare isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)

1
(v) => !R.isNil(v)è probabilmente una scelta migliore per la domanda di OP, dato che falseo altri valori falsi verrebbero anch'essi respinti daR.identity
manroe

6

Approccio funzionale e immutabile, senza .filtere senza creare più oggetti del necessario

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})

Risposta molto concisa. Per aggiungere anche il controllo null basta sostituire obj[key] === undefinedaobj[key] === undefined || obj[key] === null
user3658510

una leggera variazione dell'approccio di cui sopra: puoi anche condizionatamente diffonderti nella proprietà true obj in questo modoconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Kevin K.

6

È possibile eseguire una rimozione ricorsiva in una riga utilizzando l'argomento sostituto di json.stringify

const removeEmptyValues = obj => (
  JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)

Uso:

removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}

Come menzionato nel commento di Emmanuel, questa tecnica ha funzionato solo se la struttura dei dati contiene solo tipi di dati che possono essere inseriti in formato JSON (stringhe, numeri, elenchi, ecc.).

(Questa risposta è stato aggiornato per utilizzare il nuovo operatore di Nullish coalescenza a seconda delle esigenze di supporto del browser si consiglia di utilizzare questa funzione invece:. (k,v) => v!=null ? v : undefined)


1
questo convertirà gli oggetti Date in stringhe, convertiti NaNa nullcui non vengono rimossi.
Emmanuel NK,

5

puoi fare più corto con le !condizioni

var r = {a: null, b: undefined, c:1};
for(var k in r)
   if(!r[k]) delete r[k];

Ricorda in uso: come @semicolor annuncia nei commenti: questo eliminerebbe anche le proprietà se il valore è una stringa vuota, falsa o zero


11
Ciò eliminerebbe anche le proprietà se il valore è una stringa vuota, falsa o zero.
Punto

3
Questo era esattamente quello che stavo cercando per rimuovere i campi indesiderati da una richiesta JSON. Grazie!
Phrozen,

Usa [null, undefined].includes(r[k])invece di !r[k].
selmansamet,

5

Soluzione pura ES6 più corta, convertirla in un array, utilizzare la funzione filtro e riconvertirla in un oggetto. Sarebbe anche facile fare una funzione ...

Btw. con questo .length > 0controllo se c'è una stringa / matrice vuota, quindi rimuoverà le chiavi vuote.

const MY_OBJECT = { f: 'te', a: [] }

Object.keys(MY_OBJECT)
 .filter(f => !!MY_OBJECT[f] && MY_OBJECT[f].length > 0)
 .reduce((r, i) => { r[i] = MY_OBJECT[i]; return r; }, {});

JS BIN https://jsbin.com/kugoyinora/edit?js,console


1
Bella soluzione funzionale
puiu,

Mi piace questo! Ma penso di rimuovere tutto nulle undefinedsarebbe più semplice da usare MY_OBJECT[f] != null. La tua attuale soluzione rimuove tutto tranne le stringhe / liste non vuote e genera un errore quando i valori sononull
Rotareti,

Bene, potresti anche usare / chain multiple filter, sarebbe più leggibile.
Michael J. Zoidl,

Se lo generalizzi leggermente, penso che ti avvicini a ciò che fa Loadash omit, devi verificare che obj esista prima di chiamare Object.keys:const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
icc97

Bello, ma qualsiasi valore intero verrà rimosso con questo approccio.
Ghis,

4

Se vuoi 4 linee di una soluzione ES7 pura:

const clean = e => e instanceof Object ? Object.entries(e).reduce((o, [k, v]) => {
  if (typeof v === 'boolean' || v) o[k] = clean(v);
  return o;
}, e instanceof Array ? [] : {}) : e;

O se preferisci una versione più leggibile:

function filterEmpty(obj, [key, val]) {
  if (typeof val === 'boolean' || val) {
    obj[key] = clean(val)
  };

  return obj;
}

function clean(entry) {
  if (entry instanceof Object) {
    const type = entry instanceof Array ? [] : {};
    const entries = Object.entries(entry);

    return entries.reduce(filterEmpty, type);
  }

  return entry;
}

Ciò preserverà i valori booleani e pulirà anche le matrici. Conserva anche l'oggetto originale restituendo una copia pulita.


4

Ho lo stesso scenario nel mio progetto e realizzato usando il seguente metodo.

Funziona con tutti i tipi di dati, alcuni di cui sopra non funzionano con data e array vuoti.

removeEmptyKeysFromObject.js

removeEmptyKeysFromObject(obj) {
   Object.keys(obj).forEach(key => {
  if (Object.prototype.toString.call(obj[key]) === '[object Date]' && (obj[key].toString().length === 0 || obj[key].toString() === 'Invalid Date')) {
    delete obj[key];
  } else if (obj[key] && typeof obj[key] === 'object') {
    this.removeEmptyKeysFromObject(obj[key]);
  } else if (obj[key] == null || obj[key] === '') {
    delete obj[key];
  }

  if (obj[key]
    && typeof obj[key] === 'object'
    && Object.keys(obj[key]).length === 0
    && Object.prototype.toString.call(obj[key]) !== '[object Date]') {
    delete obj[key];
  }
});
  return obj;
}

passare qualsiasi oggetto a questa funzione removeEmptyKeysFromObject ()


4

Per una ricerca approfondita ho usato il seguente codice, forse sarà utile per chiunque guardi questa domanda (non è utilizzabile per dipendenze cicliche):

function removeEmptyValues(obj) {
        for (var propName in obj) {
            if (!obj[propName] || obj[propName].length === 0) {
                delete obj[propName];
            } else if (typeof obj[propName] === 'object') {
                removeEmptyValues(obj[propName]);
            }
        }
        return obj;
    }

3

Se non si desidera eseguire la mutazione sul posto, ma restituire un clone con il valore null / indefinito rimosso, è possibile utilizzare la funzione di riduzione ES6.

// Helper to remove undefined or null properties from an object
function removeEmpty(obj) {
  // Protect against null/undefined object passed in
  return Object.keys(obj || {}).reduce((x, k) => {
    // Check for null or undefined
    if (obj[k] != null) {
      x[k] = obj[k];
    }
    return x;
  }, {});
}

3

Invece di eliminare la proprietà, puoi anche creare un nuovo oggetto con le chiavi che non sono nulle.

const removeEmpty = (obj) => {
  return Object.keys(obj).filter(key => obj[key]).reduce(
    (newObj, key) => {
      newObj[key] = obj[key]
      return newObj
    }, {}
  )
}

3

Per piggypack sulla risposta di Ben su come risolvere questo problema utilizzando lodash di _.pickBy, è anche possibile risolvere questo problema nella biblioteca sorella: Underscore.js 's _.pick.

var obj = {name: 'John', age: null};

var compacted = _.pick(obj, function(value) {
  return value !== null && value !== undefined;
});

Vedi: Esempio JSFiddle


1
questo restituisce un array vuoto, inoltre hai cambiato il nome di obj in oggetto
Stephen DuMont,

Grazie Stefano! E adesso? Ho aggiornato la mia risposta per includere un link JSFiddle.
Alex Johnson,

prova a usare _.omit (obj, _.isEmpty); questo è concettualmente più puro e includerà una stringa vuota.
Stephen DuMont,

3

un aiutante ridotto può fare il trucco (senza controllo del tipo) -

const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
      if (value) {
        acc[key] = value;
      }
      return acc;
    }, {});

2

Se qualcuno ha bisogno di rimuovere i undefinedvalori da un oggetto con la ricerca approfondita utilizzando, lodashecco il codice che sto usando. È abbastanza semplice modificarlo per rimuovere tutti i valori vuoti ( null/ undefined).

function omitUndefinedDeep(obj) {
  return _.reduce(obj, function(result, value, key) {
    if (_.isObject(value)) {
      result[key] = omitUndefinedDeep(value);
    }
    else if (!_.isUndefined(value)) {
      result[key] = value;
    }
    return result;
  }, {});
}


1

Se usi eslint e vuoi evitare di far scattare la regola no-param-reassign, puoi usare Object.assign insieme a .reduce e un nome di proprietà calcolato per una soluzione ES6 abbastanza elegante:

const queryParams = { a: 'a', b: 'b', c: 'c', d: undefined, e: null, f: '', g: 0 };
const cleanParams = Object.keys(queryParams) 
  .filter(key => queryParams[key] != null)
  .reduce((acc, key) => Object.assign(acc, { [key]: queryParams[key] }), {});
// { a: 'a', b: 'b', c: 'c', f: '', g: 0 }

1

Ecco un modo funzionale per rimuovere nullsda un oggetto usando ES6 senza mutare l'oggetto usando solo reduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}

Commento del troll Due cose in merito al fatto che si tratta di un modello funzionale: all'interno della stripNullsfunzione utilizza un riferimento esterno all'ambito della funzione dell'accumulatore; e mescola anche le preoccupazioni filtrando all'interno della funzione accumulatore. 😝 (es. Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Sì, passerà due volte sopra gli oggetti filtrati ma la perdita di perf realizzata è trascurabile.
Jason Cust,

1

Puoi anche usare la ...sintassi diffusa usando forEachqualcosa del genere:

let obj = { a: 1, b: "b", c: undefined, d: null };
let cleanObj = {};

Object.keys(obj).forEach(val => {
  const newVal = obj[val];
  cleanObj = newVal ? { ...cleanObj, [val]: newVal } : cleanObj;
});

console.info(cleanObj);

1

Pulisci l'oggetto in posizione

// General cleanObj function
const cleanObj = (valsToRemoveArr, obj) => {
   Object.keys(obj).forEach( (key) =>
      if (valsToRemoveArr.includes(obj[key])){
         delete obj[key]
      }
   })
}

cleanObj([undefined, null], obj)

Funzione pura

const getObjWithoutVals = (dontReturnValsArr, obj) => {
    const cleanObj = {}
    Object.entries(obj).forEach( ([key, val]) => {
        if(!dontReturnValsArr.includes(val)){
            cleanObj[key]= val
        } 
    })
    return cleanObj
}

//To get a new object without `null` or `undefined` run: 
const nonEmptyObj = getObjWithoutVals([undefined, null], obj)

Questa è una soluzione piacevole, forse una linea,
rekam

1

Possiamo usare JSON.stringify e JSON.parse per rimuovere attributi vuoti da un oggetto.

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });

Questo trucco è in realtà valido, purché tu assicuri che Obj sia serializzabile JSON. E funziona anche in profondità.
Polv,

Confronto di array e oggetti non valido ( {} != {}e [] != []), ma altrimenti l'approccio è valido
Aivaras

1

Ecco una funzione ricorsiva completa (originariamente basata su quella di @chickens) che:

  • rimuovi ricorsivamente quello che dici defaults=[undefined, null, '', NaN]
  • Gestisci correttamente oggetti regolari, matrici e oggetti Date
const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
  if (!defaults.length) return obj
  if (defaults.includes(obj)) return

  if (Array.isArray(obj))
    return obj
      .map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
      .filter(v => !defaults.includes(v))

  return Object.entries(obj).length 
    ? Object.entries(obj)
        .map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
        .reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {}) 
    : obj
}

USO:

// based off the recursive cleanEmpty function by @chickens. 
// This one can also handle Date objects correctly 
// and has a defaults list for values you want stripped.

const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
  if (!defaults.length) return obj
  if (defaults.includes(obj)) return

  if (Array.isArray(obj))
    return obj
      .map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
      .filter(v => !defaults.includes(v))

  return Object.entries(obj).length 
    ? Object.entries(obj)
        .map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
        .reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {}) 
    : obj
}


// testing

console.log('testing: undefined \n', cleanEmpty(undefined))
console.log('testing: null \n',cleanEmpty(null))
console.log('testing: NaN \n',cleanEmpty(NaN))
console.log('testing: empty string \n',cleanEmpty(''))
console.log('testing: empty array \n',cleanEmpty([]))
console.log('testing: date object \n',cleanEmpty(new Date(1589339052 * 1000)))
console.log('testing: nested empty arr \n',cleanEmpty({ 1: { 2 :null, 3: [] }}))
console.log('testing: comprehensive obj \n', cleanEmpty({
  a: 5,
  b: 0,
  c: undefined,
  d: {
    e: null,
    f: [{
      a: undefined,
      b: new Date(),
      c: ''
    }]
  },
  g: NaN,
  h: null
}))
console.log('testing: different defaults \n', cleanEmpty({
  a: 5,
  b: 0,
  c: undefined,
  d: {
    e: null,
    f: [{
      a: undefined,
      b: '',
      c: new Date()
    }]
  },
  g: [0, 1, 2, 3, 4],
  h: '',
}, [undefined, null]))


0

Se preferisci l'approccio puro / funzionale

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.