我正在寻找一种能够根据某种数据格式过滤对象属性的方法。说我有这样一个对象:
var data = {
name : {
first : "Sam",
last : "Wise",
invalid : "Not A Valid Property"
},
address : "210 Test St.",
city : "Springfield",
state : "CA",
zip : "65565",
invalid_key1: "Something invalid",
invalid_key2: "Another invalid one"
}
理想情况下,我想创建一个方法,深入检查每个属性,只允许过滤对象中存在的键。我有一个适用于浅物体的版本,但是我没有想出一个聪明的方法来为子对象/数组做这个。
var controlObject = {
'name' : {
first : true,
last : true
},
'address' : true,
'city' : true,
'state' : true,
'zip' : true
};
filterObj(data, controlObject);
// Would return:
// {
// name : {
// first : "Sam",
// last : "Wise"
// },
// address : "210 Test St.",
// city : "Springfield",
// state : "CA",
// zip : "65565"
// }
这是我当前的版本,只检查一个级别。
_.mixin({
filterObj : function(data, control) {
// First set some defaults.
var _data = data || {};
var _control = control || {};
// Create arguments to be passed to _.pick()
var controlKeys = Object.keys(_control);
var args = [_data].concat(controlKeys);
// Finally use _.pick() to filter object properties.
return _.pick.apply(_, args);
}
});
我试图做一些改进以检查更深层次的对象,但它似乎没有正确地进行。
_.mixin({
filterObj : function(data, control) {
// First set some defaults.
var _data = data || {};
var _control = control || {};
// Create arguments to be passed to _.pick()
var controlKeys = Object.keys(_control);
var args = [_data].concat(controlKeys);
// Finally use _.pick() to filter object properties.
var results = _.pick.apply(_, args);
var moreKeys = Object.keys(_control).filter(function(key) {
return ( _data[key] == "object" || _data[key] == "array" ) ? true : false
});
if( moreKeys.length ) {
_.each(moreKeys, function(key) {
results[key] = _.filterObj(_data[key], _control[key]);
});
return results;
} else {
return results;
}
}
});
目前这被设置为Underscore mixin,虽然我没有与这个概念结合(只是让我在整个应用程序中更容易使用)。
答案 0 :(得分:1)
我知道这个帖子已经两年了,但我的要求与你的要求相似。除了你,我手头没有Lodash / Underscore,所以我提出了一个纯JavaScript解决方案:
function filterObj(data, control) {
var controlKeys = Object.keys(control),
results = controlKeys.reduce(function(v, key) {
if (control[key] === true && data.hasOwnProperty(key)) {
v[key] = data[key];
}
return v;
}, {});
controlKeys.filter(function(key) {
return typeof control[key] === 'object' && control[key] !== null && !Array.isArray(control[key]) && typeof data[key] === 'object' && data[key] !== null && !Array.isArray(data[key]);
}).forEach(function(key) {
results[key] = filterObj(data[key], control[key]);
});
return results;
}
var data = {
name: {
first: 'Sam',
last: 'Wise',
invalid: 'Not A Valid Property'
},
gender: 'm',
password: 'abc123',
location: {
address: '210 Test St.',
city: 'Springfield',
state: 'CA',
zip: '65565'
},
invalid_key1: 'Something invalid',
invalid_key2: 'Another invalid one'
}
var controlObject = {
name: {
first: true,
last: true
},
gender: true,
password: false,
location: true
};
console.log(filterObj(data, controlObject));
请注意我改变了初始方法的一些逻辑:
true
才能过滤掉(严格比较)希望这也有助于其他人。
答案 1 :(得分:0)
该行
return ( _data[key] == "object" || _data[key] == "array" ) ? true : false
是你的问题。您错过了typeof
运算符,并且js中没有"array"
类型 - 所有数组都是对象。我不认为你的函数无论如何都会在数组上按预期工作。更好地使用
return (typeof _data[key] == "object") && (_data[key] !== null) && !_.isArray(_data[key]);
答案 2 :(得分:0)