Entfernen Sie leere Attribute aus einem Objekt in Javascript

266

Wie entferne ich alle Attribute, die sind undefined oder nullin einem JavaScript - Objekt?

(Frage ist ähnlich wie diese für Arrays)

abhijit
quelle
19
Es wird dringend empfohlen
Evan Carroll
2
Auch ES6 One Liner ohne mutierendes Objekt ist hier: stackoverflow.com/a/57625661/1602301
Hühner

Antworten:

184

Sie können das Objekt durchlaufen:

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

Wenn Sie befürchten, dass durch das Entfernen dieser Eigenschaft die Proptypkette des Objekts nicht ausgeführt wird, können Sie außerdem:

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

Ein paar Anmerkungen zu 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
Owen
quelle
2
Eine schnelle Korrektur wurde hinzugefügt. Eine nicht deklarierte "i" -Variable würde in den äußeren Bereich gelangen, wenn dieses Snippet jemals in einer Funktion verwendet würde.
Eric Nguyen
4
Sie können das (test [i] === null || test [i] === undefined) auf (test [i] == null)
vereinfachen
Hallo, @EricNguyen, im Gegensatz zu C und anderen verschiedenen Sprachen, Javascript ist nicht Block Spielraum für Variablen (nur Funktionsumfang), so wird die Variable i leckt immer in den Bereich nach dem für Block.
Gerardo Lima
1
@ GerardoLima, ja. Ich ging davon aus, dass dies alles in eine Funktion eingebunden sein würde. Was ich damit gemeint habe (vorausgesetzt, dies ist alles mit einer Funktion umschlossen) ist, dass Sie die var-Deklaration benötigen, oder ich werde auch außerhalb des Funktionsumfangs auslaufen.
Eric Nguyen
Dadurch wird auch der Prototyp des primitiven Objekts durchlaufen - was in den meisten Fällen nicht erwünscht ist. stackoverflow.com/a/2869372/1612318
Rotareti
427

Verwendung von ES6 / ES2015 :

1) Ein einfacher Einzeiler zum Entfernen der Elemente inline ohne Zuordnung:

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

jsbin

2) Dieses Beispiel wurde entfernt ...

3) Erstes Beispiel als Funktion geschrieben:

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

jsbin

4) Diese Funktion verwendet die Rekursion , um Elemente auch aus verschachtelten Objekten zu löschen:

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) Dies ist ähnlich wie 4), aber anstatt das Quellobjekt direkt zu mutieren, wird ein neues Objekt zurückgegeben.

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) Ein funktionaler Ansatz zu 4b) basierend auf der Antwort von @ MichaelJ.Zoidl unter Verwendung von filter()und reduce(). Dieser gibt auch ein neues Objekt zurück:

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) Wie 4), jedoch mit 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) Eine andere Funktionsversion , die Rekursion verwendet und mit ES2019 ein neues Objekt zurückgibtObject.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) Wie 4), jedoch in einfachem ES5 :

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
quelle
3
@AugustinRiedinger Wenn ich mich zwischen einem Zeilenumbruch und einer Abkürzung entscheiden muss, greife ich manchmal zur Abkürzung, wenn ich denke, dass die Abkürzung das geringere Übel ist. Der Code in 5) ist nicht schwer zu begründen und es ist eine Funktion, die Leerzeichen keysaus einem entfernt object, also ound koffensichtlich ist. Aber ich denke, es ist Geschmackssache.
Rotareti
3
Erste Version mit ES5-Geschmack:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Neurotransmitter
1
Eine Zeile ohne Funktion:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm
7
Da wir versuchen, gründlich zu sein, könnte es schön sein, eine unveränderliche Lösung zu sehen. Diese mutieren das Quellobjekt und geben das Objekt täuschend zurück, was tatsächlich unnötig ist, weil das Objekt mutiert wurde. Anfänger erfassen den zurückgegebenen Objektwert und fragen sich, warum auch ihr Quellobjekt geändert wird.
Mike McLin
2
5) Funktioniert nicht mit Arrays (Object.keys gibt Array-Positionsnummern als Schlüssel für die Elemente zurück). Möglicherweise haben andere dieses Problem, aber ich habe es beim Testen von 5.
Eelco gefunden
95

Wenn Sie lodash oder underscore.js verwenden, ist hier eine einfache Lösung:

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

var compacted = _.pickBy(obj);

Dies funktioniert nur mit lodash 4, pre lodash 4 oder underscore.js _.pick(obj, _.identity).

Ben
quelle
1
Brillant! Danke dir! Zu Ihrer Information, was mir nicht klar war, ist, dass Sie es auch so verwenden können: foo (). Then (_. PickBy); // leere Ergebnisse herausfiltern
Maciej Gurban
29
Beachten Sie, dass dies nicht zum gewünschten Ergebnis führt, wenn das Objekt falsche Werte wie 0 oder leere Zeichenfolgen enthält. Dann _.omit(obj, _.isUndefined)ist es besser.
JHH
5
@JHH _.isUndefinedlässt keine Nullen aus, verwendet _.omitBy(obj, _.isNil)beide undefinedundnull
Lukasz Wiktor
@LukaszWiktor Richtig, die Frage hat nach undefiniert oder null gefragt.
JHH
87

Kürzeste Einzeiler für ES6 +

Filter alle falsy Werte ( "", 0, false, null, undefined)

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

Filter nullund undefinedWerte:

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

NUR filtern null

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

NUR filtern undefined

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

Rekursive Lösungen: Filter nullundundefined

Für Objekte:

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

Für Objekte und Arrays:

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)), {});
  } 
}
Hühner
quelle
10
Dies sollte die einzige Antwort sein! Jedes dieser Snippets generiert ein neues Objekt, bei dem das alte nicht mutiert wird. Das ist vorzuziehen! Ein kleiner Hinweis, wenn Sie nur verwenden v == null, werden Sie gegen undefinedund prüfen null.
Megajin
Die cleanEmptyrekursiven Lösungen geben ein leeres Objekt {}für Datumsobjekte zurück
Emmanuel NK
Ein bisschen mehr Lesbarkeit in den Einzeiler würde sie großartig machen !!
Zardilior
39

Wenn jemand eine rekursive Version von Owens (und Erics) Antwort benötigt, ist dies hier:

/**
 * 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
quelle
Nachdem die for-Schleife begonnen hat, sollten Sie überprüfen, ob das Objekt hasOwnPropertymitif(test.hasOwnProperty(i)) { ... }
Augie Gardner
@AugieGardner Ich bin gespannt, warum Sie dies überprüfen möchten - bitte erklären Sie es, wenn Sie möchten. (Würde es nicht die Überprüfung von geerbten Eigenschaften verhindern?)
Wumms
24

JSON.stringify entfernt die undefinierten Schlüssel.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}
Alexandre Farber
quelle
Dies funktionierte bei mir für ein tiefes Objekt nicht, aber Wumms Antwort oben tat es.
Suman
1
Wenn Sie nullals undefinedErsatzfunktion behandelt werden müssen , finden Sie weitere Informationen in dieser Antwort: stackoverflow.com/questions/286141/…
Hooman Askari
Beachten Sie jedoch, dass dadurch keine nullWerte entfernt werden. Versuchen Sie: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }und dann console.log(removeUndefined(a)). Frage war über undefinedund nullWerte.
Mayid
13

Sie suchen wahrscheinlich nach dem deleteSchlüsselwort.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
Yfeldblum
quelle
4
Dies ist, was er oben tut, dies lässt auch noch im Objekt undefiniert.
Josh Bedo
10

Einfachste mögliche Lodash Lösung ein Objekt mit dem zurück nullund undefinedWert herausgefiltert.

_.omitBy(obj, _.isNil)

JeffD23
quelle
Dies ist die bisher sauberste Lösung!
Jee Mok
9

Sie können eine Kombination aus JSON.stringifydem Ersetzungsparameter verwenden und JSON.parseihn wieder in ein Objekt verwandeln. Die Verwendung dieser Methode bedeutet auch, dass alle verschachtelten Schlüssel in verschachtelten Objekten ersetzt werden.

Beispielobjekt

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

Ersatzfunktion

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

  return value;
}

Reinigen Sie das Objekt

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

CodePen-Beispiel

Alex Mueller
quelle
6

Mit Ramda # pickBy werden Sie alle entfernen null, undefinedund falseWerte:

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

Wie @manroe betonte, verwenden Sie, um falseWerte zu verwenden isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
Amio.io
quelle
1
(v) => !R.isNil(v)ist wahrscheinlich eine bessere Wahl für die Frage von OP, da falseoder andere falsche Werte auch vonR.identity
manroe
6

Funktionaler und unveränderlicher Ansatz, ohne .filterund ohne mehr Objekte als nötig zu erstellen

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
peralmq
quelle
Sehr prägnante Antwort. So fügen Sie auch die Nullprüfung ersetzen Sie einfach obj[key] === undefinedaufobj[key] === undefined || obj[key] === null
user3658510
eine leichte Variation des obigen Ansatzes: Sie können sich auch bedingt in der wahrheitsgemäßen Eigenschaft wie folgt ausbreitenconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Kevin K.
6

Sie können eine rekursive Entfernung in einer Zeile mit durchführen Ersetzerargument von json.stringify durchführen

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

Verwendung:

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

Wie in Emmanuels Kommentar erwähnt, funktionierte diese Technik nur, wenn Ihre Datenstruktur nur Datentypen enthält, die in das JSON-Format (Zeichenfolgen, Zahlen, Listen usw.) gestellt werden können.

(Diese Antwort wurde die neuen zu verwenden , aktualisiert Nullish Coalescing Betreiber je nach Browser Support - Anforderungen können Sie diese Funktion nutzen , statt. (k,v) => v!=null ? v : undefined)

Scotty Jamison
quelle
1
Dadurch werden Datumsobjekte in Zeichenfolgen konvertiert, NaNin nulldie nicht konvertiert wird .
Emmanuel NK
5

Sie können mit !Bedingung kürzer machen

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

Denken Sie bei der Verwendung daran: wie @semicolor in Kommentaren ankündigt: Dies würde auch Eigenschaften löschen, wenn der Wert eine leere Zeichenfolge, false oder null ist

nguyên
quelle
11
Dies würde auch Eigenschaften löschen, wenn der Wert eine leere Zeichenfolge, false oder Null ist.
Semikolon
3
Dies war genau das, wonach ich gesucht habe, um unerwünschte Felder aus einer JSON-Anfrage zu entfernen. Vielen Dank!
Phrozen
Verwenden Sie [null, undefined].includes(r[k])anstelle von !r[k].
Selmansamet
5

Kürzere reine ES6-Lösung, konvertieren Sie sie in ein Array, verwenden Sie die Filterfunktion und konvertieren Sie sie zurück in ein Objekt. Wäre auch einfach eine Funktion zu machen ...

Übrigens. Damit .length > 0überprüfe ich, ob es einen leeren String / Array gibt, damit leere Schlüssel entfernt werden.

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
quelle
1
Schöne funktionale Lösung
Puiu
Ich mag das! Aber ich denke, alle zu entfernen nullund undefinedes wäre einfacher, nur zu verwenden MY_OBJECT[f] != null. Ihre aktuelle Lösung entfernt alles außer nicht leeren Zeichenfolgen / Listen und null
löst
Richtig, Sie könnten auch mehrere verwenden / verketten filter, wäre besser lesbar.
Michael J. Zoidl
Wenn Sie dies leicht verallgemeinern, denke ich, dass Sie sich dem nähern, was Loadash omitmacht, müssen Sie überprüfen, ob obj existiert, bevor Sie anrufen 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
Schön, aber jeder ganzzahlige Wert wird mit diesem Ansatz entfernt.
Ghis
4

Wenn Sie 4 Zeilen einer reinen ES7-Lösung wünschen:

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;

Oder wenn Sie eine besser lesbare Version bevorzugen:

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

Dadurch bleiben boolesche Werte erhalten und Arrays werden bereinigt. Das Originalobjekt bleibt auch erhalten, indem eine bereinigte Kopie zurückgegeben wird.

DaniOcean
quelle
4

Ich habe das gleiche Szenario in meinem Projekt und habe es mit der folgenden Methode erreicht.

Es funktioniert mit allen Datentypen, nur wenige der oben genannten funktionieren nicht mit Datums- und leeren Arrays.

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

Übergeben Sie ein beliebiges Objekt an diese Funktion. removeEmptyKeysFromObject ()

Bharath Muppa
quelle
4

Für eine gründliche Suche habe ich den folgenden Code verwendet. Vielleicht ist er für alle nützlich, die sich mit dieser Frage befassen (er kann nicht für zyklische Abhängigkeiten verwendet werden):

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
quelle
3

Wenn Sie nicht an Ort und Stelle mutieren möchten, sondern einen Klon mit entferntem null / undefined zurückgeben möchten, können Sie die ES6-Reduktionsfunktion verwenden.

// 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
quelle
3

Anstatt die Eigenschaft zu löschen, können Sie auch ein neues Objekt mit den Schlüsseln erstellen, die nicht null sind.

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

Um Bens Antwort auf die Lösung dieses Problems mit lodash's zu überprüfen _.pickBy, können Sie dieses Problem auch in der Schwesterbibliothek lösen: Underscore.js 's _.pick.

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

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

Siehe: JSFiddle-Beispiel

Alex Johnson
quelle
1
Dies gibt ein leeres Array zurück. Außerdem haben Sie den Namen von obj in object geändert
Stephen DuMont
Vielen Dank, Stephen! Wie wäre es jetzt? Ich habe meine Antwort aktualisiert und einen JSFiddle-Link hinzugefügt.
Alex Johnson
versuchen Sie es mit _.omit (obj, _.isEmpty); Dies ist konzeptionell reiner und enthält leere Zeichenfolgen.
Stephen DuMont
3

Ein Reduzierungshelfer kann den Trick machen (ohne Typprüfung) -

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

Wenn jemand undefinedWerte aus einem Objekt mit Deep Search mit entfernen muss, lodashdann ist hier der Code, den ich verwende. Es ist ganz einfach, es zu ändern, um alle leeren Werte ( null/ undefined) zu entfernen .

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
quelle
1

Mit Lodash:

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

Wenn Sie eslint verwenden und vermeiden möchten, dass die No-Param-Reignign-Regel ausgelöst wird, können Sie Object.assign in Verbindung mit .reduce und einem berechneten Eigenschaftsnamen für eine recht elegante ES6-Lösung verwenden:

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
quelle
1

Hier ist eine funktionale Möglichkeit, nullsmit ES6 aus einem Objekt zu entfernen , ohne das Objekt nur mit zu mutieren reduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}
Felippe Nardi
quelle
Trollkommentar Zwei Dinge in Bezug auf dieses Funktionsmuster: Innerhalb der stripNullsFunktion wird eine Referenz von außerhalb des Bereichs der Akkumulatorfunktion verwendet. und es mischt auch die Bedenken durch Filtern innerhalb der Akkumulatorfunktion. 😝 (zB Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Ja, die gefilterten Elemente werden zweimal
Jason Cust
1

Sie können die ...Spread-Syntax auch folgendermaßen verwenden forEach:

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
quelle
1

Reinigen Sie das Objekt an Ort und Stelle

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

cleanObj([undefined, null], obj)

Reine Funktion

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
quelle
Dies ist eine schöne, möglicherweise
einzeilige
1

Wir können JSON.stringify und JSON.parse verwenden, um leere Attribute aus einem Objekt zu entfernen.

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });
Vardaman PK
quelle
Dieser Trick ist tatsächlich gültig, solange Sie sicherstellen, dass das Objekt JSON-serialisierbar ist. Und es funktioniert auch tief.
Polv
Ungültiger Array- und Objektvergleich ( {} != {}und [] != []), aber ansonsten ist der Ansatz gültig
Aivaras
1

Hier ist eine umfassende rekursive Funktion (ursprünglich basierend auf der von @chickens), die:

  • Entfernen Sie rekursiv, was Sie ihm sagen defaults=[undefined, null, '', NaN]
  • Behandeln Sie reguläre Objekte, Arrays und Datumsobjekte korrekt
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
}

VERWENDUNG:

// 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
quelle
0

Wenn Sie den reinen / funktionalen Ansatz bevorzugen

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