如何使用lodash从对象中删除未定义和空值?

我有一个JavaScript对象,如:

var my_object = { a:undefined, b:2, c:4, d:undefined }; 

如何删除所有未定义的属性?

如果你想删除所有错误的值,那么最紧凑的方式是:

 _.pick(obj, _.identity); 

例如(Lodash 3.x):

 _.pick({ a: null, b: 1, c: undefined }, _.identity); >> Object {b: 1} 

对于Lodash 4.x:

 _.pickBy({ a: null, b: 1, c: undefined }, _.identity); >> Object {b: 1} 

你可以简单地链接_.omit()_.isUndefined_.isNull作文,并得到结果懒惰的评价。

演示

 var result = _(my_object).omit(_.isUndefined).omit(_.isNull).value(); 

2016年3月14日更新

正如注释部分中的dylants所提到的,您应该使用_.omitBy()函数,因为它使用谓词而不是属性。 你应该使用这个lodash版本4.0.0及以上。

DEMO

 var result = _(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value(); 

2016年6月1日更新

正如Max Truxa评论的,lodash已经提供了一个替代_.isNil

 var result = _.omitBy(my_object, _.isNil); 

如果您使用lodash,则可以使用_.compact(array)从数组中删除所有错误的值。

 _.compact([0, 1, false, 2, '', 3]); // => [1, 2, 3] 

https://lodash.com/docs/4.17.4#compact

只是:

 _.omit(my_object, _.isUndefined) 

上面没有考虑到null值,因为它们是从原来的例子中缺less的,只在主题中提到,但是我把它留下来,因为它很优雅,可能有它的用途。

这是一个完整的例子,不太简洁,但更完整。

 var obj = { a: undefined, b: 2, c: 4, d: undefined, e: null, f: false, g: '', h: 0 }; console.log(_.omit(obj, function(v) { return _.isUndefined(v) || _.isNull(v); })); 

根据lodash文档:

 _.compact(_.map(array, fn)) 

你也可以过滤掉所有的空值

这是我采取的方法:

 _(my_object) .pairs() .reject(function(item) { return _.isUndefined(item[1]) || _.isNull(item[1]); }) .zipObject() .value() 

pairs()函数将input对象转换为键/值数组的数组。 你这样做是为了更容易地使用reject()来消除undefinednull值。 之后,你剩下的对没有被拒绝,这些input为zipObject() ,它为你重build你的对象。

考虑到undefined == null我们可以这样写:

 let collection = { a: undefined, b: 2, c: 4, d: null, } console.log(_.omit(collection, it => it == null)) // -> { b: 2, c: 4 } 

JSBin的例子

我遇到了一个类似的问题,就是从对象(深层)中删除undefined的对象,并发现如果您可以转换普通的旧对象并使用JSON,那么一个快速又脏兮兮的辅助函数看起来像这样:

 function stripUndefined(obj) { return JSON.parse(JSON.stringify(obj)); } 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description

“…如果未定义,在转换过程中遇到函数或符号,则会将其忽略(在对象中find该对象时)或将其删除(在数组中find它时)。

用lodash(或下划线)你可以这样做

 var my_object = { a:undefined, b:2, c:4, d:undefined, e:null }; var passedKeys = _.reject(Object.keys(my_object), function(key){ return _.isUndefined(my_object[key]) || _.isNull(my_object[key]) }) newObject = {}; _.each(passedKeys, function(key){ newObject[key] = my_object[key]; }); 

否则,用香草JavaScript,你可以做

 var my_object = { a:undefined, b:2, c:4, d:undefined }; var new_object = {}; Object.keys(my_object).forEach(function(key){ if (typeof my_object[key] != 'undefined' && my_object[key]!=null){ new_object[key] = my_object[key]; } }); 

不要使用虚假的testing,因为不仅“undefined”或“null”将被拒绝 ,还有其他falsey值如“false”,“0”,空string{}。 因此,为了使其简单易懂,我select使用上面编码的显式比较。

 var my_object = { a:undefined, b:2, c:4, d:undefined }; var newObject = _.reject(my_collection, function(val){ return _.isUndefined(val) }) //--> newCollection = { b: 2, c: 4 } 

我会使用下划线和照顾空string:

 var my_object = { a:undefined, b:2, c:4, d:undefined, k: null, p: false, s: '', z: 0 }; var result =_.omit(my_object, function(value) { return _.isUndefined(value) || _.isNull(value) || value === ''; }); console.log(result); //Object {b: 2, c: 4, p: false, z: 0} 

(尽pipeObject.entries是ES7,Object.assign是ES6;但是相同的ES5使用Object.keys也应该是可行的)。 也注意v != null检查null和undefined;

 > var d = { a:undefined, b:2, c:0, d:undefined, e: null, f: 0.3, s: "", t: false }; undefined > Object.entries(d) .filter(([ k, v ]) => (v != null)) .reduce((acc, [k, v]) => Object.assign(acc, {[k]: v}), {}) { b: 2, c: 0, f: 0.3, s: '', t: false } 

编辑:这下面是只有ES5 Object.keys的版本:但通常在节点v8 ES7是非常愉快的;-)

 > Object.keys(d) .filter(function(k) { return d[k] != null; }) .reduce(function(acc, k) { acc[k] = d[k]; return acc; }, {}); { b: 2, c: 0, f: 0.3, s: '', t: false } 

2017年10月更新 :使用Node v8(自v8.3版本起)现在它具有对象扩展构造:

 > var d = { a:undefined, b:2, c:0, d:undefined, e: null, f: -0.0, s: "", t: false, inf: +Infinity, nan: NaN }; undefined > Object.entries(d) .filter(([ k, v ]) => (v != null)) .reduce((acc, [k, v]) => ({...acc, [k]: v}), {}) { b: 2, c: 0, f: -0, s: '', t: false, inf: Infinity, nan: NaN } 

或者只在一个范围内减less:

 > Object.entries(d) .reduce((acc, [k, v]) => (v==null ? acc : {...acc, [k]: v}), {}) { b: 2, c: 0, f: -0, s: '', t: false, inf: Infinity, nan: NaN } 

更新:有人想recursion? 不是那么辛苦,只需要一个额外的isObject检查,并recursion调用自己:

 > function isObject(o) { return Object.prototype.toString.call(o) === "[object Object]"; } undefined > function dropNullUndefined(d) { return Object.entries(d) .reduce((acc, [k, v]) => ( v == null ? acc : {...acc, [k]: (isObject(v) ? dropNullUndefined(v) : v) } ), {}); } > dropNullUndefined({a: 3, b:null}) { a: 3 } > dropNullUndefined({a: 3, b:null, c: { d: 0, e: undefined }}) { a: 3, c: { d: 0 } } 

我的结论是:如果纯Javascript可以做,我会避免任何第三方库依赖: