Прежде всего, считается плохой практикой расширять Object.prototype
.Вместо этого предоставьте свою функцию в качестве служебной функции на Object
, точно так же, как уже есть Object.keys
, Object.assign
, Object.is
, ... и т. Д.
Я приведу здесь несколько решений:
- Использование
reduce
и Object.keys
- As (1) в сочетании с
Object.assign
- Использование
map
и синтаксиса расширения вместо reduce
- Использование
Object.entries
и Object.fromEntries
1.Использование reduce
и Object.keys
с 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
.
2.Как (1), в сочетании с Object.assign
. В вышеприведенном решении оператор запятой используется в части reduce
для возврата измененного объекта res
.Конечно, это можно записать в виде двух утверждений вместо одного выражения, но последнее является более кратким.Чтобы сделать это без оператора запятой, вы можете использовать вместо этого Object.assign
, который делает , возвращая мутированный объект:
Object.filter = (obj, predicate) =>
Object.keys(obj)
.filter( key => predicate(obj[key]) )
.reduce( (res, key) => Object.assign(res, { [key]: obj[key] }), {} );
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);
3.Использование map
и расширенный синтаксис вместо reduce
Здесь мы вынимаем вызов Object.assign
из цикла, поэтому он делается только один раз, и передаем его отдельным ключам в качестве отдельных аргументов (используя синтаксис распространения ):
Object.filter = (obj, predicate) =>
Object.assign(...Object.keys(obj)
.filter( key => predicate(obj[key]) )
.map( key => ({ [key]: obj[key] }) ) );
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);
4.Использование Object.entries
и Object.fromEntries
Поскольку решение переводит объект в промежуточный массив, а затем преобразует его обратно в простой объект, было бы полезно использовать Object.entries
(ES2017) и использовать метод, который делает обратное (например, создает объект из массива пар ключ / значение ).На момент написания * предложение Object.fromEntries
находится на этапе 3. Firefox и, совсем недавно, Chrome реализовали его .В противном случае можно использовать polyfill.
Это приводит к этим двум «однострочным» методам на Object
(включая polyfill):
Object.fromEntries = arr => Object.assign({}, ...arr.map( ([k, v]) => ({[k]: v}) ));
Object.filter = (obj, predicate) =>
Object.fromEntries(Object.entries(obj).filter(predicate));
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, ([name, score]) => score > 1);
console.log(filtered);
Функция предиката получает здесь пару ключ / значение в качестве аргумента, которая немного отличается, но допускает больше возможностей в логике функции предиката.