O ECMAScript 5 possui o filter()
protótipo para Array
tipos, mas não para Object
tipos, se bem entendi.
Como eu implementaria um filter()
for Object
s em JavaScript?
Digamos que eu tenho esse objeto:
var foo = {
bar: "Yes"
};
E eu quero escrever um filter()
que funcione em Object
s:
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
result[key] = this[key];
}
}
return result;
};
Isso funciona quando eu o uso na demonstração a seguir, mas quando o adiciono ao meu site que usa jQuery 1.5 e jQuery UI 1.8.9, recebo erros de JavaScript no FireBug.
javascript
jquery
object
filtering
AgileMeansDoAsLittleAsPossible
fonte
fonte
Object.prototype
: bugs.jquery.com/ticket/2721Respostas:
Nunca, nunca estenda
Object.prototype
.Coisas horríveis acontecerão com o seu código. As coisas vão quebrar. Você está estendendo todos os tipos de objetos, incluindo literais de objetos.
Aqui está um exemplo rápido que você pode tentar:
Em vez disso, crie uma função para a qual você passa o objeto.
fonte
Object.prototype
, mas apenas colocar a funçãoObject
. Segundo, este é o código do OP . Claramente, a intenção do OP é.filter()
ser tal que filtre os resultados positivos. Em outras palavras, é um filtro negativo, onde um valor de retorno positivo significa que ele é excluído do resultado. Se você olhar para o exemplo jsFiddle, ele está filtrando as propriedades existentes que sãoundefined
.Object.prototype
. Da pergunta: "Isso funciona ..., mas quando o adiciono ao meu site ..., recebo erros de JavaScript" Se o OP decidir implementar um.filter()
com o comportamento oposto ao deArray.prototpe.filter
, isso é com ele. Deixe um comentário sob a pergunta se quiser notificar o OP de que o código está errado, mas não me diga que estou fazendo errado quando não é o meu código.Primeiro de tudo, é considerado uma prática ruim estender-se
Object.prototype
. Em vez disso, fornecer o seu recurso como função utilidade emObject
, assim como já existemObject.keys
,Object.assign
,Object.is
, ... etc.Eu forneço aqui várias soluções:
reduce
eObject.keys
Object.assign
map
e espalhando sintaxe em vez dereduce
Object.entries
eObject.fromEntries
1. Usando
reduce
eObject.keys
Com
reduce
eObject.keys
para implementar o filtro desejado (usando a sintaxe de seta ES6 ):Observe que no código acima
predicate
deve ser uma condição de inclusão (ao contrário da condição de exclusão usada pelo OP), para que esteja alinhado com oArray.prototype.filter
funcionamento.2. Como (1), em combinação com
Object.assign
Na solução acima, o operador de vírgula é usado na
reduce
parte para retornar ores
objeto mutado . Obviamente, isso pode ser escrito como duas declarações em vez de uma expressão, mas a última é mais concisa. Para fazê-lo sem que o operador vírgula, você poderia usarObject.assign
em vez disso, o que faz retornar o objeto mutante:3. Usando
map
e espalhar sintaxe em vez dereduce
Aqui, movemos a
Object.assign
chamada para fora do loop, para que seja feita apenas uma vez e passamos as chaves individuais como argumentos separados (usando a sintaxe de propagação ):4. Usando
Object.entries
eObject.fromEntries
Como a solução converte o objeto em uma matriz intermediária e depois a converte em um objeto simples, seria útil usar
Object.entries
(ES2017) e o oposto (por exemplo, criar um objeto a partir de uma matriz de pares de chave / valor ) comObject.fromEntries
( ES2019).Isso leva a esse método "one-liner" em
Object
:A função predicado obtém um par de chave / valor como argumento aqui, que é um pouco diferente, mas permite mais possibilidades na lógica da função predicada.
fonte
x => x.Expression.Filters.Filter
.Filter
está no final, mas se for uma função, você precisa chamá-lo (x => x.Expression.Filters.Filter()
)Se você estiver disposto a usar sublinhado ou lodash , poderá usar
pick
(ou o opostoomit
).Exemplos dos documentos de sublinhado:
Ou com um retorno de chamada (para lodash , use pickBy ):
fonte
ES6Abordagem ...
Imagine que você tem este objeto abaixo:
Crie uma função:
E chame:
e retornará :
fonte
!predicate
seu próprio código).Como Patrick já declarou, essa é uma péssima idéia, pois quase certamente quebrará qualquer código de terceiros que você possa desejar usar.
Todas as bibliotecas como jquery ou prototype serão interrompidas se você estender
Object.prototype
, o motivo é que a iteração lenta sobre objetos (semhasOwnProperty
verificações) será interrompida, pois as funções adicionadas farão parte da iteração.fonte
E se:
Ou...
fonte
Dado
então :
Mostrar snippet de código
fonte
Eu criei um
Object.filter()
que não apenas filtra por uma função, mas também aceita uma matriz de chaves para incluir. O terceiro parâmetro opcional permitirá que você inverta o filtro.Dado:
Matriz:
Função:
Código
Isenção de responsabilidade : optei por usar o núcleo Ext JS por questões de brevidade. Não considerou necessário escrever verificadores de tipos para objetos, pois isso não fazia parte da pergunta.
fonte
Minha solução opinativa:
Casos de teste:
https://gist.github.com/bernardoadc/872d5a174108823159d845cc5baba337
fonte
Solução em Vanilla JS a partir do ano 2020.
Você pode filtrar o
romNumbers
objeto por chave:Ou filtre o
romNumbers
objeto por valor:fonte
Se você deseja alterar o mesmo objeto em vez de criar um novo.
O exemplo a seguir excluirá todos os valores 0 ou vazios:
fonte
Como todos disseram, não brinque com o protótipo. Em vez disso, basta escrever uma função para fazer isso. Aqui está a minha versão com
lodash
:fonte
Eu uso isso quando preciso:
fonte
Nesses casos, eu uso o jquery $ .map, que pode manipular objetos. Como mencionado em outras respostas, não é uma boa prática alterar protótipos nativos ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes )
Abaixo está um exemplo de filtragem apenas verificando alguma propriedade do seu objeto. Retorna o próprio objeto se sua condição for verdadeira ou retornará
undefined
se não. Aundefined
propriedade fará com que esse registro desapareça da sua lista de objetos;fonte
$.map
pode pegar um objeto, mas ele retorna uma matriz, para que os nomes das propriedades originais sejam perdidos. O OP precisa de um objeto simples filtrado.