Usuń puste atrybuty z obiektu w JavaScript

265

Jak mogę usunąć wszystkie atrybuty, które są undefinedlub nullw obiektu JavaScript?

(Pytanie jest podobne do tego dla tablic)

abhijit
źródło
19
Gorąco sugeruję, aby ludzie ignorowali najwyższą pozycję i przenieśli się tutaj do wersji ES6 / ES7, stackoverflow.com/a/38340730/124486
Evan Carroll,
2
Jest tu także jeden liniowiec ES6 bez mutingu obiektu: stackoverflow.com/a/57625661/1602301
kurczaki

Odpowiedzi:

184

Możesz zapętlić obiekt:

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

Jeśli obawiasz się, że usunięcie tej właściwości nie uruchamia łańcucha proptype obiektu, możesz również:

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

Kilka uwag na temat wartości 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
piekarnik
źródło
2
Dodano szybką korektę. Niezadeklarowana zmienna „i” wyciekłaby do zakresu zewnętrznego, gdyby ten fragment kodu był kiedykolwiek używany w funkcji.
Eric Nguyen,
4
możesz uprościć (test [i] === null || test [i] === undefined) do (test [i] == null)
jaf0
Cześć, @EricNguyen, w przeciwieństwie do C i kilku innych języków, javascript nie ma zasięgu blokowego dla zmiennych (tylko zakres funkcji), dlatego zmienna i zawsze przecieka do zakresu po bloku for .
Gerardo Lima,
1
@GerardoLima, tak. W pewnym sensie zakładałem, że wszystko to będzie opakowane w funkcję. Co mam na myśli (zakładając, że jest to wszystko opakowane z funkcji) jest to, że trzeba deklarację var lub I będzie przeciekać nawet poza zakresem funkcji.
Eric Nguyen
Spowoduje to również zapętlenie prototypu obiektu pierwotnego - co w większości przypadków nie jest pożądane. stackoverflow.com/a/2869372/1612318
Rotareti,
427

Korzystanie z niektórych ES6 / ES2015 :

1) Prosta jedna linijka do usuwania elementów w linii bez przypisania:

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

jsbin

2) Ten przykład został usunięty ...

3) Pierwszy przykład napisany jako funkcja:

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

jsbin

4) Ta funkcja używa rekurencji również do usuwania elementów z zagnieżdżonych obiektów:

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) Jest to podobne do 4), ale zamiast bezpośrednio mutować obiekt źródłowy, zwraca nowy obiekt.

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) Funkcjonalne podejście do 4b) oparte na odpowiedzi @ MichaelJ.Zoidl przy użyciu filter()i reduce(). Ten zwraca również nowy obiekt:

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) Taki sam jak 4), ale z 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) Kolejna funkcjonalna wersja, która wykorzystuje rekurencję i zwraca nowy obiekt z 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) Taki sam jak 4), ale w zwykłym 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
źródło
3
@AugustinRiedinger Kiedy muszę zdecydować między przełamaniem linii a skrótem, czasami wybieram skrót, jeśli uważam, że skrót jest mniejszym złem. Kod w 5) nie jest trudny do uzasadnienia i jest to funkcja, która usuwa puste keysz object, więc oi ksą oczywiste. Ale myślę, że to kwestia gustu.
Rotareti,
3
Pierwsza wersja o smaku ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Neurotransmitter
1
Jedna linia, bez funkcji:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm
7
Ponieważ staramy się być dokładni, fajnie byłoby zobaczyć niezmienne rozwiązanie. Te mutują obiekt źródłowy i zwodniczo zwracają obiekt, który w rzeczywistości jest niepotrzebny, ponieważ obiekt został zmutowany. Początkujący przechwytują wartość zwracanego obiektu i zastanawiają się, dlaczego ich obiekt źródłowy został również zmodyfikowany.
Mike McLin
2
5) Nie działa z tablicami (Object.keys zwróci numery pozycji tablicy jako klucz do elementów). Być może inni mają ten problem, ale znalazłem to podczas testowania 5.
Eelco,
95

Jeśli używasz lodash lub underscore.js, oto proste rozwiązanie:

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

var compacted = _.pickBy(obj);

Będzie to działać tylko z lodash 4, pre lodash 4 lub underscore.js, użyj _.pick(obj, _.identity);

Ben
źródło
1
Znakomity! Dziękuję Ci! Dla ciebie nie było dla mnie oczywiste, że możesz użyć tego również w następujący sposób: foo (). Then (_. PickBy); // odfiltrowywanie pustych wyników
Maciej Gurban
29
Zauważ, że nie przyniesie to pożądanego rezultatu, jeśli obiekt zawiera wartości fałszowania, takie jak 0 lub puste ciągi. To _.omit(obj, _.isUndefined)jest lepsze.
JHH
5
@JHH _.isUndefinednie pomija zer , użyj, _.omitBy(obj, _.isNil)aby pominąć oba undefinedinull
Łukasz Wiktor
@L ŁukaszWiktor Prawidłowo, pytanie zawierało wartość niezdefiniowaną lub zerową.
JHH
85

Najkrótsza jedna wkładka do ES6 +

Odfiltrować wszystkie wartości falsy ( "", 0, false, null, undefined)

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

Filtr nulli undefinedwartości:

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

Filtruj TYLKO null

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

Filtruj TYLKO undefined

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

Rozwiązania rekurencyjne: filtry nulliundefined

W przypadku obiektów:

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

W przypadku obiektów i tablic:

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)), {});
  } 
}
kurczaki
źródło
10
To powinna być jedyna odpowiedź! Każdy z tych fragmentów wygeneruje nowy obiekt, w którym stary nie zostanie zmutowany. To jest lepsze! Mała uwaga, jeśli po prostu użyjesz v == null, sprawdzisz przeciwko undefinedi null.
Megajin
te cleanEmptyrozwiązania recursve zwróci pusty obiekt {}dla obiektów Date
Emmanuel NK
Nieco większa czytelność w jednym wkładce sprawiłaby, że byłyby niesamowite !!
zardilior
39

Jeśli ktoś potrzebuje rekurencyjnej wersji odpowiedzi Owena (i Erica), oto:

/**
 * 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
źródło
Po rozpoczęciu pętli for należy sprawdzić, czy obiekt hasOwnPropertyużywaif(test.hasOwnProperty(i)) { ... }
Augie Gardner,
@AugieGardner Jestem ciekawy, dlaczego chcesz to sprawdzić - proszę wyjaśnij, jeśli chcesz. (Czy nie zapobiegłoby to sprawdzeniu odziedziczonych właściwości?)
Wumms,
24

JSON.stringify usuwa niezdefiniowane klucze.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}
Alexandre Farber
źródło
Nie działało to dla mnie w przypadku głębokiego obiektu, ale powyższa odpowiedź Wumma ​​zadziałała .
Suman
1
Jeśli chcesz nullbyć traktowany jak undefinedskorzystaj z funkcji zastępowania, więcej informacji znajdziesz w tej odpowiedzi: stackoverflow.com/questions/286141/...
Hooman Askari
Pamiętaj, że to nie usuwa nullwartości. Spróbuj: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }a potem console.log(removeUndefined(a)). Pytanie dotyczyło undefinedi nullwartości.
mayid
13

Prawdopodobnie szukasz deletesłowa kluczowego.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
yfeldblum
źródło
4
To, co robi powyżej, również pozostawia niezdefiniowany w obiekcie.
Josh Bedo
10

Najprostsze możliwe rozwiązanie Lodash, aby zwrócić obiekt z odfiltrowanymi wartościami nulli undefined.

_.omitBy(obj, _.isNil)

JeffD23
źródło
to jak dotąd najczystsze rozwiązanie!
Jee Mok
9

Możesz użyć kombinacji JSON.stringifyparametru zastępującego i JSON.parseprzekształcić go z powrotem w obiekt. Użycie tej metody oznacza również zastąpienie wszystkich zagnieżdżonych kluczy w zagnieżdżonych obiektach.

Przykładowy obiekt

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

Funkcja zamiennika

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

  return value;
}

Oczyść obiekt

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

Przykład CodePen

Alex Mueller
źródło
6

Korzystanie ramda # pickBy można zdjąć null, undefineda falsewartości:

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

Jak wskazał @manroe, aby zachować falsewartości, użyj isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
Amio.io
źródło
1
(v) => !R.isNil(v)jest prawdopodobnie lepszym wyborem dla pytania OP, biorąc pod uwagę, że falselub inne wartości fałszowania również zostałyby odrzucone przezR.identity
manroe
6

Funkcjonalne i niezmienne podejście, .filterbez tworzenia i tworzenia większej liczby obiektów niż potrzeba

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
peralmq
źródło
Bardzo zwięzła odpowiedź. Aby dodać również kontrolę zerową, po prostu zamień obj[key] === undefinednaobj[key] === undefined || obj[key] === null
user3658510
niewielka odmiana powyższego podejścia: możesz również warunkowo rozprzestrzenić się na prawdę obj właściwość obj.const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Kevin K.,
5

możesz zrobić krócej z !warunkiem

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

Zapamiętaj w użyciu: jak @semicolor ogłasza w komentarzach: Spowoduje to również usunięcie właściwości, jeśli wartość jest pustym ciągiem, fałszem lub zerem

nguyên
źródło
11
Spowodowałoby to również usunięcie właściwości, jeśli wartością jest pusty ciąg, fałsz lub zero.
Semicolon
3
Właśnie tego szukałem, aby usunąć niechciane pola z żądania JSON. Dzięki!
Phrozen,
Użyj [null, undefined].includes(r[k])zamiast !r[k].
selmansamet
5

Krótsze rozwiązanie ES6 pure, przekonwertuj je na tablicę, użyj funkcji filtrowania i przekonwertuj z powrotem na obiekt. Łatwo byłoby również wykonać funkcję ...

Btw. dzięki temu .length > 0sprawdzam, czy jest pusty ciąg / tablica, więc usunie puste klucze.

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
źródło
1
Ładne rozwiązanie funkcjonalne
puiu
Lubię to! Ale myślę, że usunę wszystko nulli undefinedłatwiej byłoby po prostu użyć MY_OBJECT[f] != null. Twoje obecne rozwiązanie usuwa wszystko oprócz niepustych ciągów / list i generuje błąd, gdy wartości sąnull
Rotareti
Racja, możesz również użyć / łańcucha wielu filter, byłoby bardziej czytelne.
Michael J. Zoidl,
Jeśli nieco to uogólnisz, myślę, że zbliżasz się do tego, co robi loadash omit, musisz sprawdzić obj istnieje przed wywołaniem 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
Fajnie, ale każda wartość całkowita zostanie usunięta przy takim podejściu.
Ghis,
5

Możesz wykonać rekurencyjne usuwanie w jednym wierszu, używając argumentu zamiennika json.stringify

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

Stosowanie:

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

Jak wspomniano w komentarzu Emmanuela, ta technika działała tylko wtedy, gdy struktura danych zawiera tylko typy danych, które można umieścić w formacie JSON (ciągi, liczby, listy itp.).

(Ta odpowiedź została zaktualizowana do korzystania z nowego operatora Nullish koalescencyjny w zależności od potrzeb klientów przeglądarka może chcesz zamiast korzystać z tej funkcji. (k,v) => v!=null ? v : undefined)

Scotty Jamison
źródło
1
Spowoduje to konwersję obiektów Date na ciągi znaków, NaNna nullktóre nie zostaną usunięte.
Emmanuel NK
4

Jeśli chcesz 4 linie czystego rozwiązania ES7:

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;

Lub jeśli wolisz bardziej czytelną wersję:

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

Pozwoli to zachować wartości logiczne i wyczyści również tablice. Zachowuje również oryginalny obiekt, zwracając oczyszczoną kopię.

DaniOcean
źródło
4

Mam taki sam scenariusz w moim projekcie i został osiągnięty przy użyciu następującej metody.

Działa ze wszystkimi typami danych, kilka wyżej wymienionych nie działa z datą i pustymi tablicami.

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

przekazuje dowolny obiekt do tej funkcji removeEmptyKeysFromObject ()

bharath muppa
źródło
4

Do głębokiego wyszukiwania użyłem następującego kodu, być może będzie przydatny dla każdego, kto patrzy na to pytanie (nie jest to przydatne w przypadku cyklicznych zależności):

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
źródło
3

Jeśli nie chcesz mutować w miejscu, ale zwrócisz klon z usuniętą wartością null / undefined, możesz użyć funkcji redukcji 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
źródło
3

Zamiast usunąć właściwość, możesz również utworzyć nowy obiekt z kluczami, które nie mają wartości null.

const removeEmpty = (obj) => {
  return Object.keys(obj).filter(key => obj[key]).reduce(
    (newObj, key) => {
      newObj[key] = obj[key]
      return newObj
    }, {}
  )
}
Jin Zhao
źródło
3

Aby piggypack na odpowiedź Bena o tym, jak rozwiązać ten problem przy użyciu lodash użytkownika _.pickBy, można również rozwiązać ten problem w bibliotece Siostro underscore.js „s _.pick.

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

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

Zobacz: Przykład JSFiddle

Alex Johnson
źródło
1
to zwraca pustą tablicę, zmieniłeś także nazwę obiektu na obiekt
Stephen DuMont,
Dziękuję Stephen! A teraz? Zaktualizowałem swoją odpowiedź, aby zawierała link JSFiddle.
Alex Johnson
spróbuj użyć _.omit (obj, _.isEmpty); jest to bardziej koncepcyjnie czyste i będzie zawierać pusty ciąg.
Stephen DuMont
3

pomocnik redukcji może zrobić lewę (bez sprawdzania typu) -

const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
      if (value) {
        acc[key] = value;
      }
      return acc;
    }, {});
Yinon
źródło
2

Jeśli ktoś musi usunąć undefinedwartości z obiektu za pomocą głębokiego wyszukiwania, lodashoto kod, którego używam. Bardzo łatwo go zmodyfikować, aby usunąć wszystkie puste wartości ( 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
źródło
1

Z Lodash:

_.omitBy({a: 1, b: null}, (v) => !v)
Dana Woodman
źródło
1

Jeśli używasz eslint i chcesz uniknąć wyłączenia reguły no-param-reassign, możesz użyć Object.assign w połączeniu z .reduce i obliczoną nazwą właściwości dla dość eleganckiego rozwiązania ES6:

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
źródło
1

Oto funkcjonalny sposób usunięcia nullsz obiektu za pomocą ES6 bez mutowania obiektu przy użyciu tylko reduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}
Felippe Nardi
źródło
Komentarz Trolla Dwie rzeczy dotyczące tego, że jest to wzorzec funkcjonalny: w ramach stripNullsfunkcji wykorzystuje odwołanie spoza zakresu funkcji akumulatora; a także miesza obawy, filtrując w ramach funkcji akumulatora. 😝 (np. Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Tak,
Jason Cust,
1

Możesz także użyć ...składni spreadu, używając forEachczegoś takiego:

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
źródło
1

Wyczyść obiekt na miejscu

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

cleanObj([undefined, null], obj)

Czysta funkcja

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
źródło
To jest dobre, być może jedno-liniowe rozwiązanie
rekam
1

Możemy użyć JSON.stringify i JSON.parse do usunięcia pustych atrybutów z obiektu.

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });
Vardaman PK
źródło
Ta sztuczka jest faktycznie ważna, o ile upewnisz się, że Obj ma możliwość serializacji JSON. I działa również głęboko.
Polv
Niepoprawne porównanie tablic i obiektów ( {} != {}i [] != []), ale w innym przypadku poprawne jest podejście
Aivaras
1

Oto kompleksowa funkcja rekurencyjna (pierwotnie oparta na funkcji @chickens), która:

  • rekurencyjnie usuwaj to, co mówisz defaults=[undefined, null, '', NaN]
  • Prawidłowo obsługuj zwykłe obiekty, tablice i obiekty daty
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
}

STOSOWANIE:

// 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
źródło
0

Jeśli wolisz podejście czyste / funkcjonalne

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
Peter Aron Zentai
źródło