Eliminar atributos en blanco de un objeto en Javascript

Respuestas:

184

Puede recorrer el objeto:

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

Si le preocupa que esta eliminación de propiedad no ejecute la cadena de tipo de objeto, también puede:

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

Algunas notas sobre nulo vs indefinido:

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

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

test.notaprop === undefined; // true
test.notaprop == undefined; // true
Owen
fuente
2
Se agregó una corrección rápida. La variable "i" no declarada se filtraría al ámbito externo si este fragmento se utilizara alguna vez en una función.
Eric Nguyen
44
puede simplificar (test [i] === null || test [i] === undefined) a (test [i] == null)
jaf0
Hola, @EricNguyen, a diferencia de C y otros varios idiomas, javascript no no tiene ámbito de bloque para las variables (sólo ámbito de la función), por lo tanto, la variable i será siempre la fuga en el alcance después de la de bloque.
Gerardo Lima
1
@GerardoLima, sí. Estaba asumiendo que todo esto estaría envuelto en una función. Lo que quise decir (suponiendo que todo esto está envuelto con una función) es que necesita la declaración var o se me escapará incluso fuera del alcance de la función.
Eric Nguyen
Esto también recorrerá el prototipo del objeto primitivo, que en la mayoría de los casos no se desea. stackoverflow.com/a/2869372/1612318
Rotareti el
427

Usando algunos ES6 / ES2015 :

1) Una línea simple para eliminar los elementos en línea sin asignación:

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

jsbin

2) Este ejemplo fue eliminado ...

3) Primer ejemplo escrito como una función:

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

jsbin

4) Esta función también utiliza la recursión para eliminar elementos de objetos anidados:

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) Esto es similar a 4), pero en lugar de mutar el objeto fuente directamente, devuelve un nuevo objeto.

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 enfoque funcional para 4b) basado en la respuesta de @ MichaelJ.Zoidl usando filter()y reduce(). Este también devuelve un nuevo objeto:

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) Igual que 4) pero 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) Otra versión funcional que utiliza la recursión y devuelve un nuevo objeto 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) Igual que 4) pero en ES5 simple :

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

Rotareti
fuente
3
@AugustinRiedinger Cuando tengo que decidir entre un salto de línea y una abreviatura, a veces voy por la abreviatura si creo que la abreviatura es el mal menor. El código de cada 5) no es difícil razonar acerca y es una función que elimina el vacío keysde una object, por lo que oy kson evidentes. Pero supongo que es cuestión de gustos.
Rotareti
3
Primera versión con sabor ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Neurotransmisor
1
Una línea, sin función:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm
77
Como estamos tratando de ser minuciosos, podría ser bueno ver una solución inmutable. Estos están mutando el objeto fuente y están devolviendo engañosamente el objeto que en realidad es innecesario porque el objeto ha sido mutado. Los principiantes capturarán el valor del objeto devuelto y se preguntarán por qué su objeto fuente también se modifica.
Mike McLin
2
5) No funciona con matrices (Object.keys devolverá los números de posición de la matriz como la clave para los elementos). Posiblemente otros tengan este problema, pero encontré esto cuando probé 5.
Eelco
95

Si está usando lodash o underscore.js, aquí hay una solución simple:

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

var compacted = _.pickBy(obj);

Esto solo funcionará con lodash 4, pre lodash 4 o underscore.js, use _.pick(obj, _.identity);

Ben
fuente
1
¡Brillante! ¡Gracias! Para su información, lo que no era obvio para mí es que también podría usarlo así: foo (). Luego (_. PickBy); // filtrado de resultados vacíos
Maciej Gurban
29
Tenga en cuenta que esto no tendrá el resultado deseado si el objeto contiene valores falsos como 0 o cadenas vacías. Entonces _.omit(obj, _.isUndefined)es mejor.
JHH
55
@JHH _.isUndefinedno omite nulos, se usa _.omitBy(obj, _.isNil)para omitir ambos undefinedynull
Lukasz Wiktor
@LukaszWiktor Correcto, la pregunta fue indefinida o nula.
JHH
88

Los revestimientos más cortos para ES6 +

Filtrar todos los valores Falsy ( "", 0, false, null, undefined)

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

Filtro nully undefinedvalores:

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)), {})

Soluciones recursivas: filtros nullyundefined

Para objetos:

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)), {});

Para objetos y matrices:

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)), {});
  } 
}
pollos
fuente
10
¡Esta debería ser la única respuesta! Cada uno de estos fragmentos generará un nuevo objeto donde el antiguo no será mutado. ¡Esto es preferible! Una pequeña nota si solo la v == nullusas verificará contra undefinedy null.
Megajin
las cleanEmptysoluciones recursivas devolverán un objeto vacío {}para objetos Date
Emmanuel NK
¡Un poco más de legibilidad en los revestimientos los haría increíbles!
zardilior
39

Si alguien necesita una versión recursiva de la respuesta de Owen (y Eric), aquí está:

/**
 * 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);
        }
    }
}
Wumms
fuente
Después de que comience el ciclo for, debe verificar que el objeto esté hasOwnPropertyusandoif(test.hasOwnProperty(i)) { ... }
Augie Gardner
@AugieGardner Tengo curiosidad de por qué le gustaría comprobar esto, explíquelo si lo desea. (¿No evitaría la comprobación de las propiedades heredadas?)
Wumms
24

JSON.stringify elimina las claves indefinidas.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}
Alexandre Farber
fuente
Esto no funcionó para mí para un objeto profundo, pero la respuesta anterior de Wumm sí.
Suman
1
Si necesita nullser tratado como undefinedusar la función de reemplazo, para obtener más información, consulte esta respuesta: stackoverflow.com/questions/286141/…
Hooman Askari
Solo tenga en cuenta que esto no elimina los nullvalores. Prueba: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }y luego console.log(removeUndefined(a)). La pregunta era sobre undefinedy nullvalores.
mayid
13

Probablemente esté buscando la deletepalabra clave.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
Yfeldblum
fuente
44
Esto es lo que está haciendo arriba, esto también deja indefinido en el objeto.
Josh Bedo
10

La solución Lodash más simple posible para devolver un objeto con los valores nully undefinedfiltrados.

_.omitBy(obj, _.isNil)

JeffD23
fuente
¡Esta es la solución más limpia hasta ahora!
Jee Mok
9

Puede usar una combinación de JSON.stringify, su parámetro de reemplazo yJSON.parse convertirlo nuevamente en un objeto. El uso de este método también significa que el reemplazo se realiza a todas las claves anidadas dentro de los objetos anidados.

Objeto de ejemplo

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

Función de reemplazo

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

  return value;
}

Limpiar el objeto

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

Ejemplo de CodePen

Alex Mueller
fuente
6

Usando ramda # pickBy eliminará todo null, undefinedy los falsevalores:

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

Como señaló @manroe, para mantener los falsevalores use isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
Amio.io
fuente
1
(v) => !R.isNil(v)es probablemente una mejor opción para la pregunta de OP, dado que falseu otros valores falsos también serían rechazados porR.identity
manroe
6

Enfoque funcional e inmutable, sin .filtery sin crear más objetos de los necesarios

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
peralmq
fuente
Respuesta muy concisa. Para agregar también la verificación nula, simplemente reemplace obj[key] === undefinedaobj[key] === undefined || obj[key] === null
user3658510
una ligera variación del enfoque anterior: también puede difundirse condicionalmente en la propiedad obj verdadera como talconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Kevin K.
6

Puede hacer una eliminación recursiva en una línea usando el argumento de reemplazo de 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}}

Como se menciona en el comentario de Emmanuel, esta técnica solo funciona si su estructura de datos contiene solo tipos de datos que se pueden poner en formato JSON (cadenas, números, listas, etc.).

(Esta respuesta ha sido actualizado para utilizar el nuevo operador Nullish coalescente en función de las necesidades de apoyo del navegador es posible que desee utilizar esta función en lugar:. (k,v) => v!=null ? v : undefined)

Scotty Jamison
fuente
1
esto convertirá los objetos de fecha en cadenas, conversiones NaNa las nullque no se eliminan.
Emmanuel NK
5

puedes hacerlo más corto con !condición

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

Recuerde en uso: como @semicolor anuncia en los comentarios: Esto también eliminaría propiedades si el valor es una cadena vacía, falsa o cero

nguyên
fuente
11
Esto también eliminaría propiedades si el valor es una cadena vacía, falsa o cero.
Semicolon
3
Esto era exactamente lo que estaba buscando para eliminar campos no deseados de una solicitud JSON. ¡Gracias!
Phrozen
Usar en [null, undefined].includes(r[k])lugar de !r[k].
selmansamet
5

Solución pura ES6 más corta, conviértala en una matriz, use la función de filtro y vuelva a convertirla en un objeto También sería fácil hacer una función ...

Por cierto. con esto .length > 0verifico si hay una cadena / matriz vacía, por lo que eliminará las claves vacías.

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

Michael J. Zoidl
fuente
1
Buena solución funcional
Puiu
¡Me gusta esto! Pero creo que eliminar todo nully undefinedsería más fácil de usar MY_OBJECT[f] != null. Su solución actual elimina todo menos las cadenas / listas no vacías y arroja un error cuando los valores sonnull
Rotareti
Correcto, también podría usar / encadenar múltiples filter, sería más legible.
Michael J. Zoidl
Si generalizas esto un poco, creo que te acercas a lo que hace Loadash omit, debes verificar que obj existe antes de llamar 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
Agradable, pero cualquier valor entero se eliminará con este enfoque.
Ghis
4

Si desea 4 líneas de una solución 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 si prefieres una versión más legible:

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

Esto preservará los valores booleanos y también limpiará las matrices. También conserva el objeto original al devolver una copia limpia.

DaniOcean
fuente
4

Tengo el mismo escenario en mi proyecto y lo logré usando el siguiente método.

Funciona con todos los tipos de datos, algunos mencionados anteriormente no funcionan con fecha y matrices vacías.

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

pasar cualquier objeto a esta función removeEmptyKeysFromObject ()

bharath muppa
fuente
4

Para una búsqueda profunda utilicé el siguiente código, tal vez sea útil para cualquiera que esté mirando esta pregunta (no es utilizable para dependencias cíclicas):

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;
    }
sam
fuente
3

Si no desea mutar en su lugar, pero devuelve un clon con el valor nulo / indefinido eliminado, puede usar la función de reducción 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;
  }, {});
}
bsyk
fuente
3

En lugar de eliminar la propiedad, también puede crear un nuevo objeto con las claves que no son nulas.

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

Para aprovechar la respuesta de Ben sobre cómo resolver este problema usando lodash _.pickBy, también puede resolver este problema en la biblioteca hermana: Underscore.js 's _.pick.

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

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

Ver: Ejemplo de JSFiddle

Alex Johnson
fuente
1
esto devuelve una matriz vacía, también cambiaste el nombre de obj a objeto
Stephen DuMont
Gracias Stephen! ¿Que tal ahora? He actualizado mi respuesta para incluir un enlace JSFiddle.
Alex Johnson
intente usar _.omit (obj, _.isEmpty); Esto es más conceptualmente puro e incluirá una cadena vacía.
Stephen DuMont
3

un asistente de reducción puede hacer el truco (sin verificación de tipo) -

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

Si alguien necesita eliminar undefinedvalores de un objeto con una búsqueda profunda, lodashentonces aquí está el código que estoy usando. Es bastante simple modificarlo para eliminar todos los valores vacíos ( 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;
  }, {});
}
Łukasz Jagodziński
fuente
1

Con Lodash:

_.omitBy({a: 1, b: null}, (v) => !v)
Dana Woodman
fuente
1

Si usa eslint y desea evitar la desconexión de la regla de no reasignar parámetros, puede usar Object.assign junto con .reduce y un nombre de propiedad calculado para una solución ES6 bastante 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 }
dpmott
fuente
1

Aquí hay una forma funcional de eliminar nullsde un Objeto usando ES6 sin mutar el objeto usando solo reduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}
Felippe Nardi
fuente
Comentario de Troll Dos cosas con respecto a que este es un patrón funcional: dentro de la stripNullsfunción utiliza una referencia desde fuera del alcance de la función del acumulador; y también mezcla las preocupaciones al filtrar dentro de la función del acumulador. Eg (p Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});. Ej. ) Sí, recorrerá los elementos filtrados dos veces, pero la pérdida de rendimiento realizada allí es insignificante.
Jason Cust
1

También puede usar la ...sintaxis de propagación usando forEachalgo como esto:

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);
Hardik Pithva
fuente
1

Objeto limpio en su lugar

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

cleanObj([undefined, null], obj)

Función 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)
Ben Carp
fuente
Esta es una buena solución, posiblemente de una sola línea
rekam el
1

Podemos usar JSON.stringify y JSON.parse para eliminar atributos en blanco de un objeto.

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });
Vardaman PK
fuente
Este truco es realmente válido, siempre y cuando se asegure de que el Obj sea serializable por JSON. Y también funciona en profundidad.
Polv
Comparación de matriz y objeto no válida ( {} != {}y [] != []), pero por lo demás el enfoque es válido
Aivaras
1

Aquí hay una función recursiva integral (originalmente basada en la de @chickens) que:

  • eliminar recursivamente lo que le dices defaults=[undefined, null, '', NaN]
  • Manejar correctamente objetos regulares, matrices y objetos 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]))

Emmanuel NK
fuente
0

Si prefiere el enfoque puro / funcional

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
Peter Aron Zentai
fuente