Digamos que eu tenho um objeto:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
Eu quero criar um novo objeto com um subconjunto de suas propriedades.
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
Como posso conseguir isso?
javascript
Christian Schlensker
fonte
fonte
emo.slice
à primeira vista.Respostas:
Usando a destruição de objetos e a abreviação de propriedades
Partida Philipp Kewisch:
fonte
let unwrap = ({a, c}) => ({a, c}); let unwrap2 = function({a, c}) { return { a, c }; }; let picked = unwrap({ a: 5, b: 6, c: 7 });
const { b, ...picked } = object
, criariapicked
como{ a: 5, c: 7 }
. Você especificou simplesmente para remover b. Seu eslint provavelmente ficará chateado com você por declarar um var que você não está usando.Sugiro dar uma olhada no Lodash ; possui muitas funções excelentes de utilidade.
Por exemplo,
pick()
seria exatamente o que você procura:violino
fonte
_.omit(elmo, ['voice'])
para retornar tudo, excetovoice
Se você estiver usando o ES6, há uma maneira muito concisa de fazer isso usando a desestruturação. A reestruturação permite adicionar facilmente objetos usando uma propagação, mas também permite criar objetos de subconjunto da mesma maneira.
fonte
Embora seja um pouco mais detalhado, você pode realizar o que todo mundo recomendou o sublinhado / lodash por 2 anos atrás, usando Array.prototype.reduce .
Essa abordagem resolve do outro lado: em vez de pegar um objeto e passar nomes de propriedades para extrair, pegar uma matriz de nomes de propriedades e reduzi-los a um novo objeto.
Embora seja mais detalhado no caso mais simples, um retorno de chamada aqui é bastante útil, pois você pode atender facilmente a alguns requisitos comuns, por exemplo, altere a propriedade 'color' para 'color' no novo objeto, aplainar matrizes etc. - as coisas que você precisa fazer ao receber um objeto de um serviço / biblioteca e criar um novo objeto necessário em outro lugar. Embora o sublinhado / lodash sejam excelentes e bem implementadas, esta é a minha abordagem preferida para menos confiança do fornecedor e uma abordagem mais simples e consistente quando minha lógica de criação de subconjuntos fica mais complexa.
edit: es7 versão do mesmo:
editar: Um bom exemplo para curry também! Faça com que uma função 'pick' retorne outra função.
O acima é bem parecido com o outro método, exceto que permite criar um 'selecionador' em tempo real. por exemplo
O que é especialmente interessante sobre essa abordagem é que você pode facilmente passar as 'escolhas' escolhidas para qualquer coisa que desempenhe uma função, por exemplo
Array#map
:fonte
function showToy({ color, height }) {
, colocaria apenas o que você precisa em escopo. Areduce
abordagem faz sentido principalmente quando você está simplificando objetos para serialização.const pick = (obj, props) => props.reduce((a, e) => (a[e] = obj[e], a), {});
fetch
), então eu recomendo adicionar um comentário explicando o uso do operador de vírgula.ES6 desestruturação
A sintaxe da reestruturação permite desestruturar e recombinar um objeto, com parâmetros ou variáveis de função.
A limitação é que uma lista de chaves é predefinida, elas não podem ser listadas como seqüências de caracteres, conforme mencionado na pergunta. A reestruturação se torna mais complicada se uma chave não é alfanumérica, por exemplo
foo_bar
.A desvantagem é que isso requer duplicar uma lista de chaves, resultando em código detalhado, caso uma lista seja longa. Como a desestruturação duplica a sintaxe literal do objeto nesse caso, uma lista pode ser copiada e colada como está.
A vantagem é que é uma solução de alto desempenho que é natural para o ES6.
IIFE
Variáveis temporárias
Uma lista de strings
A lista arbitrária de chaves selecionadas consiste em seqüências de caracteres, conforme a pergunta. Isso permite não predefini-los e usar variáveis que contêm nomes de chave, como
pick(obj, 'foo', someKey, ...moreKeys)
.Um one-liner fica mais curto a cada edição JS.
ES5
ES6
Ou com o operador de vírgula:
ES2019
O ECMAScript 2017 possui
Object.entries
eArray.prototype.includes
, o ECMAScript 2019 possuiObject.fromEntries
, eles podem ser polyfilled quando necessário e facilitar a tarefa:Um one-liner pode ser reescrito como função auxiliar semelhante ao Lodash
pick
ouomit
onde a lista de chaves é passada através de argumentos:Uma observação sobre falta de chaves
A principal diferença entre a desestruturação e a função convencional do tipo Lodash
pick
é que a desestruturação inclui chaves selecionadas inexistentes comundefined
valor em um subconjunto:Esse comportamento pode ou não ser desejável. Não pode ser alterado para desestruturar a sintaxe.
Enquanto
pick
pode ser alterado para incluir chaves ausentes, iterando uma lista de chaves selecionadas:fonte
obj
variável seja uma variável que armazene um objeto. Se o nome da sua variável for diferente, use-o em vez deobj
.Object.keys(obj)
. Sonolento.Não há nada como isso embutido na biblioteca principal, mas você pode usar a destruição de objetos para fazer isso ...
Você também pode escrever uma função utilitária fazê-lo ...
Bibliotecas como o Lodash também possuem
_.pick()
.fonte
Estou adicionando esta resposta porque nenhuma resposta foi usada
Comma operator
.É muito fácil com
destructuring assignment
e,
operadorCom um certo aprimoramento para a atribuição de propriedades dinâmicas, pode ser assim:
fonte
'use strict'
). Eu recebo umReferenceError: a is not defined
.a
ec
- tome cuidado para não sobrescrever aleatoriamente vars locais ou globais, dependendo do contexto. (A resposta aceita evita esse problema usando duas variáveis locais em uma função inline, que cai fora do escopo após a execução imediata.)Mais uma solução:
Isso parece muito mais legível para mim do que praticamente qualquer resposta até agora, mas talvez seja apenas eu!
fonte
subset = {color: elmo.color, height: elmo.color}
, eu teria pelo menos um ... bem, um centavo talvez.Você também pode usar o Lodash .
Complementando, digamos que você tenha uma variedade de "elmo" s:
Se você deseja o mesmo comportamento, usando o lodash, basta:
fonte
A desestruturação em variáveis nomeadas dinamicamente é impossível no JavaScript, conforme discutido nesta pergunta .
Para definir teclas dinamicamente , você pode usar a função reduzir sem alterar o objeto da seguinte maneira:
abaixo está uma versão usando o botão reduzir com clone único (atualizando o valor inicial passado para reduzir).
fonte
Solução TypeScript:
As informações de digitação ainda permitem o preenchimento automático:
Crédito para DefinitelyTyped para
U extends keyof T
truque!fonte
Use o
pick
método da biblioteca lodash se você já estiver usando.https://lodash.com/docs/4.17.10#pick
fonte
Solução dinâmica
Mostrar snippet de código
fonte
Apenas outra maneira ...
Você pode usar esta função com uma matriz de objetos =)
fonte
E se:
fonte
false
(ou falso). jsfiddle.net/nfAs8keys[i] in obj
.Isso funciona para mim no console do Chrome. Algum problema com isso?
fonte
Atribuição de reestruturação com propriedades dinâmicas
Esta solução não se aplica apenas ao seu exemplo específico, mas é mais geralmente aplicável:
Você pode definir facilmente
subset4
etc. para levar mais propriedades em consideração.fonte
Bom e velho
Array.prototype.reduce
:esta resposta usa o operador de vírgula mágico, também: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
se você quiser ser realmente chique, isso é mais compacto:
Juntando tudo em uma função reutilizável:
fonte
converter argumentos em array
use
Array.forEach()
para escolher a propriedadefonte
fonte
Tentar
fonte
Adicionando meus 2 centavos à resposta de Ivan Nosov :
No meu caso, eu precisava que muitas chaves fossem 'fatiadas' do objeto, para que se tornasse feio muito rápido e não uma solução muito dinâmica:
Então, aqui está uma solução dinâmica usando eval:
fonte
você pode estender o jquery se quiser, aqui está o código de exemplo para uma fatia:
aqui está o violino para o mesmo: http://jsfiddle.net/w633z/
fonte