在Javascript中从对象中删除空白属性

515

如何在JavaScript对象中删除所有值为undefinednull的属性?

(该问题类似于此问题针对数组的解决方案)


27
强烈建议大家忽略排名靠前的版本,转而使用ES6/ES7版本,链接在这里:https://dev59.com/JnVC5IYBdhLWcg3wdw65#38340730 - Evan Carroll
5
ES6中不改变对象的一行代码也在这里:https://dev59.com/JnVC5IYBdhLWcg3wdw65#57625661 - chickens
ES6 -> JSON.parse(JSON.stringify(obj)) 的意思是将一个对象进行深拷贝。 - STEEL
2
小心!这两个都不能用于数组。 - Martin D
请查看链接,您不仅可以清除null或undefined,甚至可以定义自定义值以删除。 https://dev59.com/JnVC5IYBdhLWcg3wdw65#71968391 - ABHIJEET KHIRE
显示剩余3条评论
55个回答

8

去除所有值为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.log(result)


8

你可以使用!条件来简化代码

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

使用时请记住:如@semicolor在评论中所述:如果值为空字符串、false或零,则会删除属性


14
如果值为空字符串、false或零,这也会删除属性。 - Semicolon
3
这正是我想要的,用来从JSON请求中删除不需要的字段。谢谢! - Phrozen
1
使用[null, undefined].includes(r[k])代替!r[k] - sametcodes

7
使用 Ramda#pickBy,您可以删除所有 nullundefinedfalse 值:
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) is probably a better choice for OP's question, given that false or other falsy values would also be rejected by R.identity - manroe

7

我在项目中遇到了相同的情况,并使用以下方法实现。

它适用于所有数据类型,但其中一些(如日期和空数组)不适用。

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()。

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
以上方法的一个小变化:你也可以有条件地展开真值对象属性,如下所示const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {}); - Kevin K.
“{...acc,[key]:obj [key]}”在reduce函数中不是一项相对昂贵的操作吗?因为每次评估都会将键复制到新对象中?保持相同的对象并添加新项目是否会更快? - Lucas Moeskops

6
较短的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 BIN https://jsbin.com/kugoyinora/edit?js,console

JS BIN是一个在线的代码编辑器和调试工具,可以帮助开发者快速创建和测试代码。以上链接是一个示例页面,在页面上你可以尝试修改代码并实时查看结果。

1
不错的功能性解决方案。 - puiu
我喜欢这个!但是我认为,要删除所有的nullundefined,最简单的方法就是使用MY_OBJECT[f] != null。你目前的解决方案只删除非空字符串/列表,当值为null时会抛出错误。 - Rotareti
你也可以使用/链接多个filter,这样会更易读。 - Michael J. Zoidl
如果你稍微泛化一下,我认为你会接近于lodash的omit函数所做的事情,但是在调用 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
不错,但是这种方法会删除任何整数值。 - Ghis
这适用于空对象吗?例如JSON { f: 'te', a: [], b: {}, c: { c1: {} } } 应该得到 { f: 'te' } - AndyDaSilva52

5

以下是我使用的深度搜索代码,对于正在查看此问题的任何人可能会有用(它不能用于循环依赖):

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

5
以下是一份综合性递归函数(最初基于@chickens的代码),它可以:
  • 递归地删除您指定的内容 defaults=[undefined, null, '', NaN]
  • 正确处理普通对象、数组和日期对象
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]))


5

这里有一个替代方案:

Typescript:

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

5

除了删除属性之外,你还可以创建一个新的对象,其中包含不为空的键。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接