Удалить пустые атрибуты из объекта в Javascript

Как удалить все атрибуты undefined или null в объекте JavaScript?

(Вопрос аналогичен Вот этот для массивов)

Настоятельно рекомендую людям игнорировать высший ранг и перейти к версиям ES6 / ES7 здесь, stackoverflow.com/a/38340730/124486

Evan Carroll 13.12.2016 10:54

Также здесь ES6 one liners без мутирующего объекта: stackoverflow.com/a/57625661/1602301

chickens 27.08.2019 14:40
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
327
2
286 937
40
Перейти к ответу Данный вопрос помечен как решенный

Ответы 40

Вероятно, вы ищете ключевое слово delete.

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

Это то, что он делает выше, это также по-прежнему оставляет undefined в объекте.

Josh Bedo 24.07.2014 19:54
Ответ принят как подходящий

Вы можете пройти по объекту в цикле:

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

console.info(test);
console.info(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 и 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

Добавлено быстрое исправление. Необъявленная переменная "i" просочилась бы во внешнюю область видимости, если бы этот фрагмент кода когда-либо использовался в функции.

Eric Nguyen 16.12.2013 10:11

вы можете упростить (test [i] === null || test [i] === undefined) до (test [i] == null)

jaf0 24.05.2015 06:01

Привет, @EricNguyen, в отличие от C и других языков, в javascript нет есть область блока для переменных (только область действия), поэтому переменная яя> всегда будет попадать в область после блока для.

Gerardo Lima 10.05.2016 12:54

@GerardoLima, да. Я как бы предполагал, что все это будет заключено в функцию. Я имел в виду (при условии, что все это обернуто функцией), что вам нужно объявление var, иначе яя> будет протекать даже за пределами области действия функции.

Eric Nguyen 14.05.2016 05:32

Это также будет проходить через прототип примитивного объекта, что в большинстве случаев нежелательно. stackoverflow.com/a/2869372/1612318

Rotareti 08.08.2016 01:26

@Rotareti только что обновил ответ, включив в него ответ, который ограничивается собственными свойствами объекта.

Eric Nguyen 23.09.2016 03:32

Не могли бы вы взглянуть на этот вопрос: stackoverflow.com/questions/42783607/…

Vishal 19.03.2017 09:26

плюс один для null vs undefined :)

Gel 19.06.2019 23:14

можно сделать короче с условием !

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

Помните в использовании: как @semicolor анонсирует в комментариях: Это также приведет к удалению свойств, если значение является пустой строкой, ложью или нулем.

Это также приведет к удалению свойств, если значение является пустой строкой, ложью или нулем.

Semicolon 19.03.2014 01:35

Это было именно то, что я искал, чтобы удалить ненужные поля из запроса JSON. Спасибо!

Phrozen 06.10.2014 04:51

Используйте [null, undefined].includes(r[k]) вместо !r[k].

samet 13.10.2018 16:06

Если кому-то нужна рекурсивная версия ответа Оуэна (и Эрика), вот она:

/**
 * 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 19.10.2016 09:01

@AugieGardner Мне любопытно, почему вы хотите это проверить - пожалуйста, объясните, если хотите. (Разве это не помешало бы проверке унаследованных свойств?)

Wumms 19.10.2016 20:32

JSON.stringify удаляет неопределенные ключи.

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

У меня это не сработало для глубокого объекта, но Ответ Вумма выше сработало.

Suman 01.04.2016 22:47

Если вам нужно, чтобы null рассматривался как undefined, используйте функцию замены, для получения дополнительной информации обратитесь к этому ответу: stackoverflow.com/questions/286141/…

Hooman Askari 30.01.2017 14:12

Просто имейте в виду, что это не удаляет значения null. Попробуйте: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }, а затем console.info(removeUndefined(a)). Вопрос касался значений undefined и null.

mayid 18.12.2019 18:45

Методы JSON предназначены для строк json и никогда не должны использоваться для объектов javascript без надлежащего анализа и проверки.

Maciej Kwas 13.11.2020 23:55

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

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

Если вы используете lodash или underscore.js, вот простое решение:

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

var compacted = _.pickBy(obj);

Это будет работать только с lodash 4, pre lodash 4 или underscore.js, используйте _.pick(obj, _.identity);

Блестяще! Спасибо! К вашему сведению, что для меня не было очевидным, так это то, что вы можете использовать его также так: foo (). Then (_. PickBy); // отфильтровываем пустые результаты

Maciej Gurban 02.08.2016 23:36

Обратите внимание, что это не приведет к желаемому результату, если объект содержит ложные значения, такие как 0 или пустые строки. Тогда лучше _.omit(obj, _.isUndefined).

JHH 23.05.2017 14:49

@JHH _.isUndefined не пропускает нули, используйте _.omitBy(obj, _.isNil), чтобы опустить как undefined, так и null

Lukasz Wiktor 29.02.2020 10:50

@LukaszWiktor Правильно, в вопросе действительно задано значение undefined или null.

JHH 02.03.2020 12:21

Чтобы скопировать на Ответ бена, как решить эту проблему с помощью lodash _.pickBy, вы также можете решить эту проблему в родственной библиотеке: Underscore.js's _.pick.

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

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

См .: Пример JSFiddle

это возвращает пустой массив, также вы изменили имя obj на объект

Stephen DuMont 21.04.2017 01:52

Спасибо, Стивен! Как насчет сейчас? Я обновил свой ответ, добавив ссылку на JSFiddle.

Alex Johnson 21.04.2017 17:14

попробуйте использовать _.omit (obj, _.isEmpty); это более концептуально чисто и будет включать пустую строку.

Stephen DuMont 24.04.2017 07:50

Если кому-то нужно удалить значения 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;
  }, {});
}

Примеры ES10 / ES2019

Простой однострочный (возврат нового объекта).

let o = Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));

То же, что и выше, но написано как функция.

function removeEmpty(obj) {
  return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));
}

Эта функция использует рекурсия для удаления элементов из вложенных объектов.

function removeEmpty(obj) {
  return Object.fromEntries(
    Object.entries(obj)
      .filter(([_, v]) => v != null)
      .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v])
  );
}

Примеры ES6 / ES2015

Простой однострочный. Предупреждение: это изменяет данный объект вместо возврата нового.

Object.keys(obj).forEach((k) => obj[k] == null && delete obj[k]);

Одно объявление (не изменяющее данный объект).

let o = Object.keys(obj)
  .filter((k) => obj[k] != null)
  .reduce((a, k) => ({ ...a, [k]: obj[k] }), {});

То же, что и выше, но написано как функция.

function removeEmpty(obj) {
  return Object.entries(obj)
    .filter(([_, v]) => v != null)
    .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
}

Эта функция использует рекурсию для удаления элементов из вложенных объектов.

function removeEmpty(obj) {
  return Object.entries(obj)
    .filter(([_, v]) => v != null)
    .reduce(
      (acc, [k, v]) => ({ ...acc, [k]: v === Object(v) ? removeEmpty(v) : v }),
      {}
    );
}

То же, что и функция выше, но написано в императивном (нефункциональном) стиле.

function removeEmpty(obj) {
  const newObj = {};
  Object.entries(obj).forEach(([k, v]) => {
    if (v === Object(v)) {
      newObj[k] = removeEmpty(v);
    } else if (v != null) {
      newObj[k] = obj[k];
    }
  });
  return newObj;
}

Примеры ES5 / ES2009

Раньше все было намного многословнее.

Это нерекурсивная версия, написанная в функциональном стиле.

function removeEmpty(obj) {
  return Object.keys(obj)
    .filter(function (k) {
      return obj[k] != null;
    })
    .reduce(function (acc, k) {
      acc[k] = obj[k];
      return acc;
    }, {});
}

Это нерекурсивная версия, написанная в императивном стиле.

function removeEmpty(obj) {
  const newObj = {};
  Object.keys(obj).forEach(function (k) {
    if (obj[k] && typeof obj[k] === "object") {
      newObj[k] = removeEmpty(obj[k]);
    } else if (obj[k] != null) {
      newObj[k] = obj[k];
    }
  });
  return newObj;
}

И рекурсивная версия, написанная в функциональном стиле.

function removeEmpty(obj) {
  return Object.keys(obj)
    .filter(function (k) {
      return obj[k] != null;
    })
    .reduce(function (acc, k) {
      acc[k] = typeof obj[k] === "object" ? removeEmpty(obj[k]) : obj[k];
      return acc;
    }, {});
}

Что касается №5, вы подразумеваете, что функциональный => нечитаемый? Зачем использовать o и k, когда в каждом другом примере вы используете object и key?

Augustin Riedinger 13.12.2016 18:14

@AugustinRiedinger Когда мне приходится выбирать между переносом строки и сокращением, я иногда использую аббревиатуру, если считаю, что аббревиатура - меньшее зло. Код в 5) нетрудно понять, и это функция, которая удаляет пустой keys из object, поэтому o и k очевидны. Но думаю, это дело вкуса.

Rotareti 13.12.2016 20:10

Первая версия с ароматом ES5: Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});

Neurotransmitter 01.03.2017 13:14

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

Paul Slm 10.05.2017 20:20

Я поддержал ваш ответ, но когда я увидел, что вы опускаете фигурные скобки, я действительно хотел отозвать мой голос: \

Ervin Llojku 23.08.2017 12:23

В # 6 val === null должен быть val == null (т.е. использовать оператор равенства вместо оператора идентичности). Аналогично, в №7 obj[key] === null должен быть obj[key] == null.

Ron Martinez 26.08.2017 05:21

Мне это нравится, большое спасибо

Nguyễn Anh Tuấn 22.11.2017 12:16

Поскольку мы стараемся быть внимательными, было бы неплохо увидеть неизменное решение. Они изменяют исходный объект и обманчиво возвращают объект, который на самом деле не нужен, потому что объект был изменен. Новички будут фиксировать возвращаемое значение объекта и удивляться, почему их исходный объект тоже изменяется.

Mike McLin 30.01.2018 00:58

@MikeMcLin Хороший вопрос! 5) уже неизменен, но я добавил 4b), что является обязательным подходом к 5). Я также удалил оператор return из функций, изменяющих исходный объект. Теперь должно быть меньше путаницы. Я также удалил 2), так как это не имеет смысла.

Rotareti 30.01.2018 10:05

Та же версия, что и 5), но короче:

Michal Moravcik 23.08.2018 23:07

Та же версия, что и 5), только короче: const removeEmpty = (obj) => return Object.keys (obj) .filter (k => obj [k]! == null && obj [k]! == undefined) // Удалить undefined и null .reduce ((newObj, k) => (newObj [k] = typeof obj [k] === 'object'? removeEmpty (obj [k]): obj [k], newObj), {}) ;

Michal Moravcik 23.08.2018 23:09

Как я могу удалить «отца», у которого больше есть атрибуты? например, у объекта все атрибуты были равны нулю, так в чем смысл сохранения объекта живым, я хочу удалить отца, если дочерние элементы больше не существуют, как я могу?

Paulo Roberto Rosa 29.11.2018 01:13

5) Не работает с массивами (Object.keys будет возвращать номера позиций массива в качестве ключа для элементов). Возможно, у других есть эта проблема, но я обнаружил это при тестировании 5.

Eelco 13.06.2019 22:25

Случай 4 работал у меня с небольшой модификацией условия else if (obj [key] == null || obj [key] == ''). Таким образом, я могу удалять элементы с пустыми строками (без символов и без пробелов).

Williams A. 30.12.2019 15:00

Ухххх. Мне жаль, что я не копировал слепо одно из них. Я сходил с ума от DynamoDB. Пожалуйста, проверьте наличие Array.isArray(obj) перед typeof obj === 'object'. Array.isArray (obj) === true и typeof obj === 'object' пройдут.

Will Farley 17.03.2020 17:16

Чем он лучше JSON.parse(JSON.stringify(obj, (k,v) => v==null?undefined:v)), упомянутого в stackoverflow.com/a/54707141/906265?

Aivaras 20.03.2020 18:01

@Rotareti, почему я отменил предложение, которое я сделал, используя новую функцию для фрагмента кода, которая позволяет Stack правильно выполнять код javascript? Было ли это из-за использования console.info()? Я также исправил [7], потому что функция должна возвращать объект return obj;.

AndyDaSilva52 15.12.2020 18:57

@Rotareti А что, когда есть только фигурные скобки {} ??? Например, JSON { g: {}, h: "test" }, который должен приводить к { h: "test" }

AndyDaSilva52 29.12.2020 01:54

Вы можете использовать комбинацию JSON.stringify, его параметра replacer и 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

Для тех, кто использует машинописный текст или более новую версию node / js, это более короткая версия. const clean = (object: object) => JSON.parse(JSON.stringify(object, (_, value) => value ?? undefined));

Alexis Tyler 15.08.2020 08:36

Используя 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)
(v) => !R.isNil(v), вероятно, является лучшим выбором для вопроса OP, учитывая, что false или другие ложные значения также будут отклонены R.identity
manroe 08.05.2018 22:18

С Lodash:

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

Это удалит также 0 или пустую строку '', лучше будет _.omitBy({a: 1, b: null, c: undefined, d: 0, e: ''}, (v) => typeof v !== undefined && typeof v !== 'null')

bukso 29.03.2021 11:44

Если вы не хотите мутировать на месте, но возвращаете клон с удаленными значениями 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;
  }, {});
}

Вместо удаления свойства вы также можете создать новый объект с ключами, которые не равны нулю.

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

Более короткое чистое решение ES6, преобразовать его в массив, использовать функцию фильтрации и преобразовать обратно в объект. Также было бы легко сделать функцию ...

Кстати. с этим .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 BINhttps://jsbin.com/kugoyinora/edit?js,console

Хорошее функциональное решение

puiu 15.05.2017 19:06

Мне это нравится! Но я думаю, что для удаления всех null и undefined было бы проще просто использовать MY_OBJECT[f] != null. Ваше текущее решение удаляет все, кроме непустых строк / списков, и выдает ошибку, когда значения равны null.

Rotareti 13.06.2017 03:53

Правильно, вы также можете использовать / связать несколько filter, было бы более читабельно.

Michael J. Zoidl 13.06.2017 09:27

Если вы немного обобщите это, я думаю, вы приблизитесь к тому, что делает loadash omit, вам нужно проверить, существует ли obj, прежде чем вызывать 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 19.10.2018 09:07

Хорошо, но при таком подходе любое целочисленное значение будет удалено.

Ghis 13.12.2018 18:18

Это работает для пустой объект? Ex JSON { f: 'te', a: [], b: {}, c: { c1: {} } }, который должен привести к { f: 'te' }

AndyDaSilva52 29.12.2020 02:30

Простейшее возможное решение Lodash для возврата объекта с отфильтрованными значениями null и undefined.

_.omitBy(obj, _.isNil)

на данный момент это самое чистое решение!

Jee Mok 23.10.2018 07:06

Если вы используете eslint и хотите избежать срабатывания правила no-param-reassign, вы можете использовать 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 }

Если вам нужны 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;
}

Это сохранит логические значения, а также очистит массивы. Он также сохраняет исходный объект, возвращая очищенную копию.

У меня такой же сценарий в моем проекте, и я использовал следующий метод.

Он работает со всеми типами данных, некоторые из упомянутых выше не работают с датами и пустыми массивами.

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

передать любой объект в эту функцию removeEmptyKeysFromObject ()

Вот функциональный способ удалить 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;}, {});) Да, он дважды перебирает отфильтрованные элементы, но реализованные потери производительности незначительны.
Jason Cust 03.08.2018 23:10

Чистый объект на месте

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

Это хорошее, возможно, однострочное решение

rekam 26.09.2018 12:20

помощник reduce может сделать трюк (без проверки типов) -

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

Вы также можете использовать синтаксис ...spread, используя 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);

Если вы предпочитаете чистый / функциональный подход

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

Если вы не хотите изменять исходный объект (используя некоторые операторы ES6):

const keys = Object.keys(objectWithNulls).filter(key => objectWithNulls[key]);
const pairs = keys.map(key => ({ [key]: objectWithNulls[key] }));

const objectWithoutNulls = pairs.reduce((val, acc) => ({ ...val, ...acc }));

filter(key => objectWithNulls[key]) возвращает все, что правда, поэтому отклоняет любые значения, такие как 0 или false, а также undefined или null. Может быть легко заменен на filter(key => objectWithNulls[key] !== undefined) или что-то подобное, если это нежелательное поведение.

Вы можете выполнить рекурсивное удаление в одной строке, используя Аргумент replacer json.stringify

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

Использование:

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

Как упоминалось в комментарии Эммануэля, этот метод работал только в том случае, если ваша структура данных содержит только типы данных, которые могут быть помещены в формат JSON (строки, числа, списки и т. д.).

(Этот ответ был обновлен для использования нового Оператор Nullish Coalescing. В зависимости от потребностей поддержки браузера вы можете вместо этого использовать эту функцию: (k,v) => v!=null ? v : undefined)

это преобразует объекты Date в строки, преобразует NaN в null, которые не удаляются.

Emmanuel N K 13.05.2020 10:39

Рекурсивно удалять пустые, неопределенные, пустые объекты и пустые массивы, возвращая копию (версия ES6)

export function skipEmpties(dirty) {
    let item;
    if (Array.isArray(dirty)) {
        item = dirty.map(x => skipEmpties(x)).filter(value => value !== undefined);
        return item.length ? item : undefined;
    } else if (dirty && typeof dirty === 'object') {
        item = {};
        Object.keys(dirty).forEach(key => {
            const value = skipEmpties(dirty[key]);
            if (value !== undefined) {
                item[key] = value;
            }
        });
        return Object.keys(item).length ? item : undefined;
    } else {
        return dirty === null ? undefined : dirty;
    }
}

Функциональный и неизменный подход, без .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 14.08.2019 20:17

небольшая вариация вышеупомянутого подхода: вы также можете условно распространить в истинном свойстве obj, например, const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});

Kevin K. 13.09.2019 16:50

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

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

Этот трюк действительно действителен, если вы убедитесь, что Obj сериализуем в формате JSON. И это тоже работает глубоко.

Polv 05.01.2020 12:27

Неверное сравнение массивов и объектов ({} != {} и [] != []), но в остальном подход допустим.

Aivaras 20.03.2020 17:56

Самый короткий лайнер для ES6 +

Отфильтровать все ложные значения ("", 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)), {});
  } 
}

Это должен быть единственный ответ! Каждый из этих фрагментов будет генерировать новый объект, в котором старый не будет изменен. Это предпочтительнее! Небольшое примечание, если вы просто используете v == null, вы будете проверять его по undefined и null.

Megajin 26.08.2019 15:29

рекурсивные решения cleanEmpty вернут пустой объект {} для объектов Date.

Emmanuel N K 13.05.2020 07:03

Немного больше разборчивости в одинарных вкладышах сделало бы их потрясающими !!

zardilior 09.06.2020 22:12

Также хорошо работает с TypeScript. Object.entries (record) .reduce ((a: Anything, [k, v]) => (v.length! == 0? (A [k] = v, a): a), {}) где интерфейс Что-нибудь {[ключ: строка]: строка; }

Alex Nolasco 23.07.2020 04:21

Можно ли удалить из массивов только null, а не объекты ... как это изменить :). Пожалуйста помоги :)

GOXR3PLUS 12.10.2020 14:46

Что вы имеете в виду @ GOXR3PLUS? удаление нулей из массивов так же просто, как arr = arr.filter(v=>v!==null)

Superole 26.11.2020 10:43

@Superole Well i am trying to modify the above to remove the nulls only from the arrays inside the object. Поэтому я хочу, чтобы он касался только массивов внутри объекта и оставлял простые пары значений ключа нетронутыми, даже если значение равно нулю. Но если значение - массив [1,2,null,5,null], чтобы обрезать нули внутри массивов :)

GOXR3PLUS 26.11.2020 14:52

@chickens а что насчет пустой объект? Пример: JSON { g: {}, h: "test" }, что приводит к { h: "test" }.

AndyDaSilva52 29.12.2020 02:06

a, [k, v] => аккумулятор, ключ, значение

chickens 02.03.2021 07:45

30+ ответов, но я не видел этого короткого однострочника ES6, использующего оператор распространения благодаря тому, что Object.assign() является функцией vararg, которая молча игнорирует любые не-объекты (например, false).

Object.assign({}, ...Object.entries(obj).map(([k,v]) => v != null && {[k]: v]))

Сбой во вложенной структуре: {1:{2:null}}

Aivaras 20.03.2020 17:47

Если вы просто хотите удалить неопределенные свойства верхнего уровня из объекта, я считаю, что это самый простой вариант:

const someObject = {
  a: null,
  b: 'someString',
  c: 3,
  d: undefined
};

for (let [key, value] of Object.entries(someObject)) {
  if (value === null || value === undefined) delete someObject[key];
}

console.info('Sanitized', someObject);
ES6 arrow function and ternary operator:
Object.entries(obj).reduce((acc, entry) => {
   const [key, value] = entry
  if (value !== undefined) acc[key] = value;
  return acc;
}, {})
    const obj = {test:undefined, test1:1 ,test12:0, test123:false};
    const newObj = Object.entries(obj).reduce((acc, entry) => {
       const [key, value] = entry
      if (value !== undefined) acc[key] = value;
      return acc;
    }, {})
    console.info(newObj)

Вот комплексная рекурсивная функция (изначально основанная на функции @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.info('testing: undefined \n', cleanEmpty(undefined))
console.info('testing: null \n',cleanEmpty(null))
console.info('testing: NaN \n',cleanEmpty(NaN))
console.info('testing: empty string \n',cleanEmpty(''))
console.info('testing: empty array \n',cleanEmpty([]))
console.info('testing: date object \n',cleanEmpty(new Date(1589339052 * 1000)))
console.info('testing: nested empty arr \n',cleanEmpty({ 1: { 2 :null, 3: [] }}))
console.info('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.info('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]))

удалить объект пустого поля

for (const objectKey of Object.keys(data)) {
      if (data[objectKey] === null || data[objectKey] === '' || data[objectKey] === 'null' || data[objectKey] === undefined) {
        delete data[objectKey];
      }
    }

На этот вопрос уже дан исчерпывающий ответ, я просто хотел бы поделиться своей версией на основе других приведенных примеров:

function filterObject(obj, filter) {
    return Object.entries(obj)
        .map(([key, value]) => {
            return [key, value && typeof value === 'object'
                ? filterObject(value, filter)
                : value];
        })
        .reduce((acc, [key, value]) => {
            if (!filter.includes(value)) {
                acc[key] = value;
            }

            return acc;
        }, {});
}

Что отличает это решение, так это возможность указать, какие значения вы хотите фильтровать во втором параметре следующим образом:

const filtered = filterObject(originalObject, [null, '']);

Что вернет новый объект (не изменяет исходный объект), не включая свойства со значением null или ''.

Вот альтернатива

Машинопись:

function objectDefined <T>(obj: T): T {
  const acc: Partial<T> = {};
  for (const key in obj) {
    if (obj[key] !== undefined) acc[key] = obj[key];
  }
  return acc as T;
}

Javascript:

function objectDefined(obj) {
  const acc = {};
  for (const key in obj) {
    if (obj[key] !== undefined) acc[key] = obj[key];
  }
  return acc;
}

Если вас устраивает использование Лодаш, вы можете добавить рекурсивную библиотеку DeepDash и добиться желаемого с помощью довольно краткого кода:

const prune = obj => _.filterDeep(obj, (v) => !(_.isUndefined(v) || _.isNull(v)));

Вызов prune(anObjectWithNulls) вернет объект без значений undefined или null.

Удалите все свойства с null и undefined

let obj = {
"id": 1,
"firstName": null,
"lastName": null,
"address": undefined,
"role": "customer",
"photo": "fb79fd5d-06c9-4097-8fdc-6cebf73fab26/fc8efe82-2af4-4c81-bde7-8d2f9dd7994a.jpg",
"location": null,
"idNumber": null,
};

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

Другие вопросы по теме