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

IT技术 javascript
2021-01-26 02:21:08

如何删除JavaScript 对象undefined其中的所有属性null

(问题类似于这一个的阵列)

6个回答

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) 不适用于数组(Object.keys 将返回数组位置编号作为元素的键)。可能其他人也有这个问题,但我在测试 5 时发现了这个问题。
2021-03-18 02:21:08
一行,无功能: Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
2021-03-19 02:21:08
@AugustinRiedinger 当我必须在换行符和缩写之间做出决定时,如果我认为缩写的危害较小,我有时会选择缩写。在5代码)不难推理,这是一个函数,删除空keysobject,所以ok是显而易见的。但我想这是一个品味问题。
2021-03-27 02:21:08
ES5 风格的第一个版本: Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
2021-03-31 02:21:08
由于我们正在努力做到彻底,因此看到一个不可变的解决方案可能会很好。这些正在改变源对象并欺骗性地返回实际上不必要的对象,因为该对象已被改变。初学者将捕获返回的对象值并想知道为什么他们的源对象也被修改了。
2021-04-04 02:21:08

您可以遍历对象:

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.log(test);
console.log(clean(test));

如果您担心此属性删除不会运行对象的 proptype 链,您还可以:

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
您可以将 (test[i]===null || test[i]===undefined) 简化为 (test[i]==null)
2021-03-20 02:21:08
您好,@EricNguyen,不同于C等几种语言,JavaScript并没有对变量块范围(仅功能范围),因此,可变将总是泄漏到后的范围块。
2021-03-27 02:21:08
添加了快速更正。如果此代码段曾在函数中使用过,则未声明的“i”变量将泄漏到外部作用域。
2021-03-30 02:21:08
这也将遍历原始对象的原型——在大多数情况下这是不希望的。stackoverflow.com/a/2869372/1612318
2021-04-07 02:21:08
@GerardoLima,是的。我有点假设这将全部包含在一个函数中。我的意思是(假设这一切都用一个函数包装)是你需要 var 声明,否则会泄漏甚至超出函数范围。
2021-04-08 02:21:08

最短的 ES6+ 内衬

过滤所有虚假值 ( "", 0, false, null, undefined)

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

过滤器nullundefined值:

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

递归解决方案:过滤器nullundefined

对于对象:

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注意一点,您将检查undefinednull
2021-03-11 02:21:08
也适用于 TypeScript。Object.entries(record).reduce((a: Everything, [k, v]) => (v.length !== 0 ? (a[k] = v, a) : a), {}) where interface任何 { [key: string]: string; }
2021-03-16 02:21:08
@GOXR3PLUS 是什么意思?从数组中删除空值就像arr = arr.filter(v=>v!==null)
2021-03-23 02:21:08
cleanEmptyrecursve解决方案将返回一个空的对象{}为Date对象
2021-03-30 02:21:08
单衬里多一点易读性会让它们很棒!!
2021-04-10 02:21:08

如果您使用 lodash 或 underscore.js,这里有一个简单的解决方案:

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

var compacted = _.pickBy(obj);

这仅适用于 lodash 4、pre lodash 4 或 underscore.js,使用_.pick(obj, _.identity);

@JHH_.isUndefined不省略空值,用于_.omitBy(obj, _.isNil)省略undefinednull
2021-03-14 02:21:08
@LukaszWiktor 正确,问题确实要求 undefined 或 null。
2021-03-22 02:21:08
请注意,如果对象包含虚假值(例如 0 或空字符串),则这不会产生所需的结果。然后_.omit(obj, _.isUndefined)更好。
2021-04-05 02:21:08
杰出的!谢谢!仅供参考,对我来说不明显的是你也可以像这样使用它:foo().then(_.pickBy); // 过滤空结果
2021-04-07 02:21:08

如果有人需要欧文(和埃里克)答案的递归版本,这里是:

/**
 * 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)) { ... }
2021-03-19 02:21:08
@AugieGardner 我很好奇你为什么要检查这个 - 如果你愿意,请解释一下。(它不会阻止检查继承的属性吗?)
2021-03-28 02:21:08