Видаліть порожні атрибути з об’єкта в JavaScript


265

Як видалити всі атрибути, які є undefinedабо є nullв об’єкті JavaScript?

(Питання схоже на таке для Arrays)


19
Дуже пропоную людям ігнорувати першокласні та переходити до версій ES6 / ES7 тут, stackoverflow.com/a/38340730/124486
Еван Керролл

2
Також тут є один лайнер ES6 без мутаційного об’єкта: stackoverflow.com/a/57625661/1602301
кури

Відповіді:


184

Ви можете провести цикл через об'єкт:

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

Якщо ви стурбовані тим, що це видалення властивості не працює з ланцюжком прототипів об'єкта, ви також можете:

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

Кілька приміток про 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
Додано швидке виправлення. Недекларована змінна "i" просочиться у зовнішню сферу, якби цей фрагмент коли-небудь використовувався у функції.
Ерік Нгуен

4
ви можете спростити (test [i] === null || test [i] === undefined) to (test [i] == null)
jaf0

Привіт, @EricNguyen, на відміну від C та інших кількох мов, javascript не має блокової області для змінних (лише область функцій), таким чином, змінна i завжди буде просочуватися в область після блоку для .
Джерардо Ліма

1
@GerardoLima, так. Я начебто припускав, що це все буде обгорнуто функцією. Що я мав на увазі (припускаючи, що це все завершено функцією), це те, що вам потрібна декларація var, або я просочується навіть поза межами функції.
Ерік Нгуен

Це також пройде через прототип примітивного об'єкта - що в більшості випадків не є бажаним. stackoverflow.com/a/2869372/1612318
Rotareti

427

Використання деяких ES6 / ES2015 :

1) Простий однолінійний інструмент для видалення елементів в рядку без призначення:

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

jsbin

2) Цей приклад видалено ...

3) Перший приклад, записаний як функція:

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

jsbin

4) Ця функція використовує рекурсію і для видалення елементів з вкладених об'єктів:

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) Це схоже на 4), але замість того, щоб безпосередньо вимкнути вихідний об'єкт, він повертає новий об'єкт.

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) Функціональний підхід до 4b), заснований на відповіді @ MichaelJ.Zoidl з використанням filter()і reduce(). Цей також повертає новий об’єкт:

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) Те саме, що і 4), але з 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) Ще одна функціональна версія, яка використовує рекурсію та повертає новий об’єкт з 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) Те саме, що і 4), але в звичайному 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


3
@AugustinRiedinger Коли мені доводиться вирішувати між розривом рядків та абревіатурою, я іноді йду за абревіатурою, якщо я вважаю, що абревіатура є меншим злом. Код у 5) не важко міркувати, і це функція, яка видаляє порожнє keysз object, так oі kочевидні. Але я думаю, це справа смаку.
Ротарети

3
Перша версія з ароматом ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Нейромедіатор

1
Один рядок, без функції:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Пол Slm

7
Оскільки ми намагаємося бути ретельними, може бути приємно побачити незмінне рішення. Вони мутують вихідний об'єкт і обманливо повертають об'єкт, який насправді є непотрібним, оскільки об'єкт був вимкнено. Початківці захоплюють повернене значення об'єкта і задаються питанням, чому також змінюється їх вихідний об’єкт.
Майк Маклін

2
5) Не працює з масивами (Object.keys повертає номери позицій масиву як ключ для елементів). Можливо, інші мають цю проблему, але я виявив це під час тестування 5.
Eelco

95

Якщо ви використовуєте lodash або underscore.js, ось просте рішення:

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

var compacted = _.pickBy(obj);

Це буде працювати лише з lodash 4, pre lodash 4 або underscore.js, use _.pick(obj, _.identity);


1
Блискуче! Дякую! FYI, мені було не очевидно, що ти можеш використовувати його також так: foo (). Then (_. PickBy); // фільтрування порожніх результатів
Maciej Gurban

29
Зауважте, що це не матиме бажаного результату, якщо об’єкт містить помилкові значення, такі як 0 або порожні рядки. Тоді _.omit(obj, _.isUndefined)краще.
JHH

5
@JHH _.isUndefinedне опускає нулі, використовуй, _.omitBy(obj, _.isNil)щоб опустити і те, undefinedіnull
Лукаш Віктор,

@LukaszWiktor Правильно, запитання було задано невизначеним або недійсним.
JHH

85

Найкоротший один вкладиш для ES6 +

Фільтр за все falsy значення ( "", 0, false, null, undefined)

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

Фільтр nullта undefinedзначення:

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

Фільтр ТІЛЬКИ null

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

Фільтр ТІЛЬКИ undefined

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

Рекурсивні рішення: Фільтри nullтаundefined

Для об'єктів:

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

Для об'єктів та масивів:

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
Це має бути єдиною відповіддю! Кожен з цих фрагментів генерує новий об’єкт, коли старий не буде вимкнено. Це бажано! Маленька примітка, якщо ви просто використовуєте, v == nullви будете перевіряти проти undefinedта null.
Megajin

то cleanEmptyrecursve рішення повертає порожній об'єкт {}для об'єктів Дати
Еммануель NK

Трохи більше розбірливості в одному вкладиші зробить їх приголомшливими !!
zardilior

39

Якщо комусь потрібна рекурсивна версія відповіді Оуена (та Еріка), ось це:

/**
 * 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);
        }
    }
}

Після початку циклу for, ви повинні перевірити, чи hasOwnPropertyвикористовується об'єктif(test.hasOwnProperty(i)) { ... }
Augie Gardner

@AugieGardner Мені цікаво, чому ви хочете перевірити це - будь ласка, поясніть це, якщо вам подобається. (Чи не завадить це перевірити спадкові властивості?)
Wumms

24

JSON.stringify видаляє не визначені ключі.

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

Це не спрацювало для мене з глибоким об'єктом, але відповідь Вюмма вище .
Суман

1
Якщо вам потрібно nullбуде розглядатися як undefinedвикористання функції заміни, для отримання додаткової інформації зверніться до цієї відповіді: stackoverflow.com/questions/286141 / ...
Hooman Аскарі

Пам’ятайте, що значення не видаляє null. Спробуйте: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }і тоді console.log(removeUndefined(a)). Питання було про undefinedі nullзначення.
mayid

13

Ви, ймовірно, шукаєте deleteключове слово.

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

4
Це те, що він робить вище, це також залишає невизначеним в об'єкті.
Джош Бедо

10

Найпростіше можливе рішення Лодаша, щоб повернути об'єкт із значеннями nullі undefinedвідфільтрованими значеннями.

_.omitBy(obj, _.isNil)


це найчистіше рішення поки що!
Jee Mok

9

Ви можете використовувати комбінацію параметра JSON.stringify, його замінника, і JSON.parseповернути його назад в об'єкт. Використання цього методу також означає, що заміна виконується для всіх вкладених ключів у вкладених об'єктах.

Приклад об’єкта

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

Функція замінника

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

  return value;
}

Очистіть об’єкт

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

Приклад CodePen


6

Використання ramda # pickBy ви видалите всі null, undefinedі falseзначення:

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

Як вказував @manroe, щоб falseвикористовувати значення 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)це, мабуть, кращий вибір для питання ОП, враховуючи, що falseабо інші фальшиві цінності також будуть відкинуті користувачемR.identity
manroe

6

Функціональний та незмінний підхід, .filterбез створення та без створення більшої кількості об'єктів, ніж потрібно

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

Дуже лаконічна відповідь. Щоб також додати нульову перевірку, просто замініть obj[key] === undefinedнаobj[key] === undefined || obj[key] === null
user3658510

незначна зміна вищезазначеного підходу: ви також можете умовно поширюватись у властивості truthy obj, як такconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Кевін К.

5

ви можете зробити коротше з !умовою

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

Пам’ятайте про використання: як @semicolor оголосити в коментарях: Це також видалить властивості, якщо значення порожній рядок, помилкове або нульове


11
Це також видалить властивості, якщо значення порожній рядок, помилкове або нульове.
напівколонка

3
Це саме те, що я шукав, щоб видалити небажані поля із запиту JSON. Дякую!
заморожений

Використовуйте [null, undefined].includes(r[k])замість !r[k].
selmansamet

5

Коротше чисте рішення ES6, конвертуйте його в масив, використовуйте функцію фільтра та перетворіть його назад на об'єкт. Було б також легко зробити функцію ...

Btw. з цим .length > 0я перевіряю, чи є порожній рядок / масив, тому він видалить порожні ключі.

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
Приємне функціональне рішення
puiu

Мені подобається це! Але я думаю, що все видалити, nullі просто undefinedбуло б просто використовувати MY_OBJECT[f] != null. Ваше поточне рішення видаляє все, крім порожніх рядків / списків, і видає помилку, коли значенняnull
Rotareti

Правильно, ви також можете використовувати / ланцюгові множини filter, було б читабельніше.
Michael J. Zoidl

Якщо ви трохи узагальнили це, я думаю, ви наблизитесь до того, що omitробить loadash , вам потрібно перевірити, чи існує Object.keysconst omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
Obj,

Добре, але будь-яке ціле значення буде видалено за допомогою цього підходу.
Ghis

5

Ви можете зробити рекурсивне видалення в одному рядку, використовуючи аргумент-замінник json.stringify

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

Використання:

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

Як згадується в коментарі Еммануеля, ця методика працювала лише в тому випадку, якщо ваша структура даних містить лише типи даних, які можна ввести у формат JSON (рядки, числа, списки тощо).

(Ця відповідь був оновлений , щоб використовувати новий оператор Nullish коалесцирует в залежності від потреб підтримки браузера ви можете використовувати цю функцію замість :. (k,v) => v!=null ? v : undefined)


1
це буде конвертувати Дата об'єктів в рядки, звернені NaNдо nullякої не видаляються.
Еммануель НК

4

Якщо ви хочете 4 рядки чистого рішення 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;

Або якщо ви віддаєте перевагу більш читаній версії:

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

Це збереже булеві значення і також очистить масиви. Він також зберігає оригінальний об'єкт, повертаючи очищену копію.


4

У мене такий же сценарій у моєму проекті і досягнуто, використовуючи наступний метод.

Він працює з усіма типами даних, кілька згаданих вище не працює з датами та порожніми масивами.

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

передайте будь-який об’єкт цій функції deleteEmptyKeysFromObject ()


4

Для глибокого пошуку я використав наступний код, можливо, він буде корисний для всіх, хто переглядає це питання (він не використовується для циклічних залежностей):

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

Якщо ви не хочете мутувати на місці, але повернути клон з вилученим null / undefined, ви можете скористатися функцією зменшення 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

Замість того, щоб видалити властивість, ви також можете створити новий об’єкт за допомогою клавіш, які не є нульовими.

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

3

Щоб скласти скаргу на відповідь Бена про те, як вирішити цю проблему за допомогою лодаша _.pickBy, ви також можете вирішити цю проблему в сестринській бібліотеці: Underscore.js 's _.pick.

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

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

Див.: Приклад JSFiddle


1
це повертає порожній масив, також ви змінили назву obj на об'єкт
Stephen DuMont

Дякую, Стівен! Як щодо тепер? Я оновив свою відповідь, щоб включити посилання JSFiddle.
Алекс Джонсон

спробуйте використовувати _.omit (obj, _.isEmpty); це більш концептуально чисто і буде включати порожню рядок.
Стівен Дюмон

3

помічник зменшення може виконати трюк (без перевірки типу) -

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

2

Якщо комусь потрібно видалити undefinedзначення з об'єкта при глибокому пошуку, використовуючи lodashкод, який я використовую. Це досить просто змінити, щоб видалити всі порожні значення ( 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

Якщо ви використовуєте eslint і хочете уникнути відключення правила no-param-reasign, ви можете використовувати Object.assign у поєднанні з .reduce та обчисленою назвою властивості для досить елегантного рішення 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 }

1

Ось функціональний спосіб видалення nullsз Об'єкта за допомогою ES6 без мутації об'єкта лише за допомогою reduce:

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

Коментар Троля Дві речі щодо цього є функціональним зразком: у межах stripNullsфункції він використовує посилання поза сферою функції акумулятора; і це також змішує проблеми, фільтруючи в межах функції акумулятора. 😝 (наприклад Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Так, він
Джейсон Касто

1

Ви також можете використовувати ...синтаксис розповсюдження, використовуючи 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);

1

Чистий предмет на місці

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

cleanObj([undefined, null], obj)

Чиста функція

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)

Це гарне, можливо,
однолінійне

1

Ми можемо використовувати JSON.stringify та JSON.parse для видалення порожніх атрибутів з об’єкта.

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

Цей трюк дійсно дійсний, якщо ви переконаєтесь, що Obj є JSON-серіалізаційним. І це також працює глибоко.
Полв

Неправильний порівняння масиву та об’єктів ( {} != {}і [] != []), але в іншому випадку підхід діє
Айварас

1

Ось комплексна рекурсивна функція (спочатку заснована на функції від @chickens), яка буде:

  • рекурсивно видаліть те, що вам сказали defaults=[undefined, null, '', NaN]
  • Правильно обробляти регулярні об'єкти, масиви та об'єкти 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
}

ВИКОРИСТАННЯ:

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

Якщо ви віддаєте перевагу чистий / функціональний підхід

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.