Eu gostaria de criar um objeto com um membro adicionado condicionalmente. A abordagem simples é:
var a = {};
if (someCondition)
a.b = 5;
Agora, eu gostaria de escrever um código mais idiomático. Eu estou tentando:
a = {
b: (someCondition? 5 : undefined)
};
Mas agora, b
é um membro a
cujo valor é undefined
. Este não é o resultado desejado.
Existe uma solução útil?
Atualizar
Eu procuro uma solução que possa lidar com o caso geral com vários membros.
a = {
b: (conditionB? 5 : undefined),
c: (conditionC? 5 : undefined),
d: (conditionD? 5 : undefined),
e: (conditionE? 5 : undefined),
f: (conditionF? 5 : undefined),
g: (conditionG? 5 : undefined),
};
javascript
viebel
fonte
fonte
a.b
, a recuperaçãoa.b
retornaria deundefined
qualquer maneira.in
operador é usado.Respostas:
No Javascript puro, não consigo pensar em nada mais idiomático do que o seu primeiro trecho de código.
Se, no entanto, o uso da biblioteca jQuery não estiver fora de questão, $ .extend () deverá atender aos seus requisitos, pois, como diz a documentação:
Portanto, você pode escrever:
E obtenha os resultados esperados (se
conditionB
houverfalse
, entãob
não existirãoa
).fonte
Acho que o @InspiredJW fez isso com o ES5 e, como o @trincot apontou, usar o es6 é uma abordagem melhor. Mas podemos adicionar um pouco mais de açúcar usando o operador spread e a avaliação lógica E de curto-circuito:
fonte
Null/Undefined Are Ignored
, ela não diz quefalse
é ignorada. Os transpilers podem permitir isso até o momento, mas é compatível? O seguinte deve ser,{...someCondition ? {b: 5} : null}
mas não é tão compacto.Object.assign
e tem precedência menor do que o operador &&. Ele ignora o valor sem propriedade (booleano, nulo, indefinido, número) e adiciona todas as propriedades do objeto após o...
local. lembre-se de que o&&
operador retornará o valor correto se verdadeiro, ou falso caso contrário. por isso, sesomeCondition
for verdade,{b : 5}
será passado para o...
operador, resultando em adição a propriedadeb
paraa
com o valor5
. ésomeCondition
false,false
será passado para o...
operador. resultando em nada adicionado. é inteligente. Eu amo isso.Com o EcmaScript2015, você pode usar
Object.assign
:Mostrar snippet de código
Algumas observações:
Object.assign
modifica o primeiro argumento no local, mas também retorna o objeto atualizado: para que você possa usar esse método em uma expressão maior que manipule ainda mais o objeto.null
você poderia passarundefined
ou{}
, com o mesmo resultado. Você pode até fornecer0
, porque os valores primitivos são quebrados eNumber
não possuem propriedades enumeráveis próprias .Ainda mais conciso
Tomando ainda mais o segundo ponto, você pode reduzi-lo da seguinte forma (como @Jamie tem fora pontas), como valores Falsas não têm próprias propriedades enumeráveis (
false
,0
,NaN
,null
,undefined
,''
, com exceçãodocument.all
):Mostrar snippet de código
fonte
Demonstração ao vivo:
fonte
O uso de sintaxe de propagação com booleano (como sugerido aqui) não é uma sintaxe válida. A propagação só pode ser usada com iterables .
Sugiro o seguinte:
fonte
{...false}
{...false}
é uma sintaxe válida.CopyDataProperties
é realizada no valor (false
neste caso). Isso envolve o boxe de uma primitiva (seções 7.3.23, 7.1.13). O link que você tem para o MDN menciona essa "exceção" entre parênteses.Que tal usar as Propriedades Avançadas do Objeto e definir a propriedade apenas se for verdade, por exemplo:
Portanto, se a condição não for atendida, ela não criará a propriedade preferida e, portanto, você poderá descartá-la. Consulte: http://es6-features.org/#ComputedPropertyNames
ATUALIZAÇÃO: É ainda melhor seguir a abordagem de Axel Rauschmayer em seu artigo de blog sobre a adição condicional de entradas em literais e matrizes de objetos ( http://2ality.com/2017/04/conditional-literal-entries.html ):
Me ajudou bastante.
fonte
false
chave extra . Por exemplo,{[true && 'a']: 17, [false && 'b']: 42}
is{a:17, false: 42}
...isConditionTrue() && { propertyName: 'propertyValue' }
mais simplificado,
fonte
Se o objetivo é fazer com que o objeto pareça independente e esteja dentro de um conjunto de chaves, você pode tentar o seguinte:
fonte
Se você deseja fazer esse lado do servidor (sem jquery), pode usar o lodash 4.3.0:
E isso funciona usando o lodash 3.10.1
fonte
Espero que seja a maneira mais eficiente de adicionar uma entrada com base na condição. Para obter mais informações sobre como adicionar entradas condicionais dentro de literais de um objeto.
fonte
[...condition?'':['item']]
isto irá adicionar item de string em arrayIsso tem sido respondido há muito tempo, mas, olhando para outras idéias, eu vim com uma derivada interessante:
Atribua valores indefinidos à mesma propriedade e exclua-a posteriormente
Criar o objeto usando um construtor anónimo e sempre atribuir membros indefinidos para o mesmo manequim membro que você remove no final. Isso fornecerá uma única linha (não muito complexa, espero) por membro + 1 linha adicional no final.
fonte
Você pode adicionar todos os seus valores indefinidos sem condição e, em seguida, usar
JSON.stringify
para remover todos eles:fonte
Eu faria isso
Editado com uma versão de código de linha
fonte
a = undefined
. Pode ser facilmente alterado comreturn { b: undefined };
: /return {};
emelse
partea = condition ? {b:5} : undefined;
Usando a biblioteca lodash, você pode usar _.omitBy
Isso é útil quando você tem solicitações opcionais
fonte
Eu acho que sua primeira abordagem para adicionar membros condicionalmente é perfeitamente correta. Eu realmente não concordo com não querer ter um membro
b
dea
com um valor deundefined
. É simples o suficiente para adicionar umaundefined
verificação com o uso de umfor
loop com oin
operador. De qualquer forma, você pode facilmente escrever uma função para filtrarundefined
membros.Você também pode usar o
delete
operador para editar o objeto no local.fonte
Quebrar em um objeto
Algo assim é um pouco mais limpo
Agrupar em uma matriz
Ou, se você quiser usar o método de Jamie Hill e tiver uma lista muito longa de condições, deverá escrever a
...
sintaxe várias vezes. Para torná-lo um pouco mais limpo, basta envolvê-los em uma matriz e usáreduce()
-los para devolvê-los como um único objeto.Ou usando a
map()
funçãofonte
Esta é a solução mais sucinta que posso encontrar:
fonte
Usando a biblioteca lodash, você pode usar _.merge
false
& conditionC fortrue
, entãoa = { c: 5 }
true
, entãoa = { b: 4, c: 5 }
false
, entãoa = {}
fonte
lodash@^4.0.0
.undefined
estão sendo incluídos no meu caso.