JavaScript: filter() для объектов
ECMAScript 5 имеет filter() прототип Array типы, но не Object типы, если я правильно понял.
как бы я реализовал filter() на Objects в JavaScript?
скажем, у меня есть этот объект:
var foo = {
bar: "Yes"
};
и я хочу написать filter() что работает на Objects:
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
result[key] = this[key];
}
}
return result;
};
это работает, когда я использую его в следующей демонстрации, но когда я добавляю его на свой сайт, который использует jQuery 1.5 и jQuery UI 1.8.9, я получаю Ошибки JavaScript в FireBug.
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
console.log("copying");
result[key] = this[key];
}
}
return result;
};
var foo = {
bar: "Yes",
moo: undefined
};
foo = foo.filter(function(property) {
return typeof property === "undefined";
});
document.getElementById('disp').innerHTML = JSON.stringify(foo, undefined, ' ');
console.log(foo);
#disp {
white-space: pre;
font-family: monospace
}
<div id="disp"></div>8 ответов:
никогда и нигде не распространяется
Object.prototype.ужасные вещи будут происходить с вашим кодом. Все сломается. Вы расширяетесь все типы объектов, включая литералы объектов.
вот быстрый пример, который вы можете попробовать:
// Extend Object.prototype Object.prototype.extended = "I'm everywhere!"; // See the result alert( {}.extended ); // "I'm everywhere!" alert( [].extended ); // "I'm everywhere!" alert( new Date().extended ); // "I'm everywhere!" alert( 3..extended ); // "I'm everywhere!" alert( true.extended ); // "I'm everywhere!" alert( "here?".extended ); // "I'm everywhere!"
вместо этого создайте функцию, которую вы передаете объекту.
Object.filter = function( obj, predicate) { var result = {}, key; // ---------------^---- as noted by @CMS, // always declare variables with the "var" keyword for (key in obj) { if (obj.hasOwnProperty(key) && !predicate(obj[key])) { result[key] = obj[key]; } } return result; };
прежде всего,считается плохой практикой расширять
Object.prototype. Вместо этого предоставьте свою функцию в качестве функции полезности наObject, так же, как уже естьObject.keys,Object.assign,Object.is, ...так далее.можно использовать
reduceиObject.keysдля реализации нужного фильтра (с помощью ES6 синтаксис стрелой):Object.filter = (obj, predicate) => Object.keys(obj) .filter( key => predicate(obj[key]) ) .reduce( (res, key) => (res[key] = obj[key], res), {} ); // Example use: var scores = { John: 2, Sarah: 3, Janet: 1 }; var filtered = Object.filter(scores, score => score > 1); console.log(filtered);обратите внимание, что в приведенном выше коде
predicateдолжен быть включение состояние (вопреки исключение условие OP используется), так что он находится в соответствии с тем, какArray.prototype.filterстроительство.С
Object.assignв приведенном выше решении оператор запятая используется
reduceчасть, чтобы вернуть мутировавший
если вы используете подчеркивание или лодашь, вы можете использовать
pick(или, напротив,omit).примеры из документов подчеркивания:
_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age'); // {name: 'moe', age: 50}или с обратным вызовом (для лодашь используйте pickBy):
_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) { return _.isNumber(value); }); // {age: 50}
как Патрик уже заявил, Это плохая идея, так как она почти наверняка сломает любой сторонний код, который вы когда-либо хотели бы использовать.
все библиотеки, такие как jquery или prototype, сломаются, если вы расширите
Object.prototype, причина в том, что ленивая итерация над объектами (безhasOwnPropertyпроверки) сломается, так как функции, которые вы добавляете, будут частью итерации.
Я создал
Object.filter()который не только фильтрует по функции, но и принимает массив ключей для включения. Дополнительный третий параметр позволит вам инвертировать фильтр.дано:
var foo = { x: 1, y: 0, z: -1, a: 'Hello', b: 'World' }время:
Object.filter(foo, ['z', 'a', 'b'], true);функция:
Object.filter(foo, function (key, value) { return Ext.isString(value); });код
отказ от ответственности: я решил использовать Ext JS core для краткости. Не посчитал нужным писать шашки типов для типов объектов как это не было частью вопроса.
// Helper functions function clone(obj) { return JSON.parse(JSON.stringify(obj)); } function print(obj) { document.getElementById('disp').innerHTML += JSON.stringify(obj, undefined, ' ') + '<br />'; console.log(obj); } Object.filter = function (obj, ignore, invert) { if (ignore === undefined) { return obj; } invert = invert || false; var not = function(condition, yes) { return yes ? !condition : condition; }; var isArray = Ext.isArray(ignore); for (var key in obj) { if (obj.hasOwnProperty(key) && (isArray && not(!Ext.Array.contains(ignore, key), invert)) || (!isArray && not(!ignore.call(undefined, key, obj[key]), invert))) { delete obj[key]; } } return obj; }; var foo = { x: 1, y: 0, z: -1, a: 'Hello', b: 'World' }, bar = clone(foo); print(Object.filter(foo, ['z', 'a', 'b'], true)); print(Object.filter(bar, function (key, value) { return Ext.isString(value); }));#disp { white-space: pre; font-family: monospace }<script src="https://cdnjs.cloudflare.com/ajax/libs/extjs/4.2.1/builds/ext-core.min.js"></script> <div id="disp"></div>
дано
object = {firstname: 'abd', lastname:'tm', age:16, school:'insat'}; keys = ['firstname', 'age'];затем :
keys.reduce((result, key) => ({ ...result, [key]: object[key] }), {}); // {firstname:'abd', age: 16}// Helper function filter(object, ...keys) { return keys.reduce((result, key) => ({ ...result, [key]: object[key] }), {}); }; //Example const person = {firstname: 'abd', lastname:'tm', age:16, school:'insat'}; // Expected to pick only firstname and age keys console.log( filter(person, 'firstname', 'age') )
Как насчет:
function filterObj(keys, obj) { const newObj = {}; for (let key in obj) { if (keys.includes(key)) { newObj[key] = obj[key]; } } return newObj; }или...
function filterObj(keys, obj) { const newObj = {}; Object.keys(obj).forEach(key => { if (keys.includes(key)) { newObj[key] = obj[key]; } }); return newObj; }
в этих случаях я использую jquery $.карта, которая может обрабатывать объекты. Как уже упоминалось в других ответах, не рекомендуется менять собственные прототипы (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes)
Ниже приведен пример фильтрации, просто проверяя некоторые свойства вашего объекта. Он возвращает собственный объект, если ваше условие истинно или возвращает
undefinedесли не. Этотundefinedсвойство сделает эту запись исчезнет из списка объектов;$.map(yourObject, (el, index)=>{ return el.yourProperty ? el : undefined; });