No meu código, lido com um array que possui algumas entradas com muitos objetos aninhados uns dentro dos outros, enquanto alguns não. É algo parecido com o seguinte:
// where this array is hundreds of entries long, with a mix
// of the two examples given
var test = [{'a':{'b':{'c':"foo"}}}, {'a': "bar"}];
Isso está me causando problemas porque às vezes preciso iterar pela matriz, e a inconsistência está me gerando erros como:
for (i=0; i<test.length; i++) {
// ok on i==0, but 'cannot read property of undefined' on i==1
console.log(a.b.c);
}
Estou ciente do que posso dizer if(a.b){ console.log(a.b.c)}
, mas isso é extremamente tedioso nos casos em que há até 5 ou 6 objetos aninhados um dentro do outro. Existe alguma outra maneira (mais fácil) de fazer com que SOMENTE faça o console.log se ele existir, mas sem gerar um erro?
javascript
Ari
fonte
fonte
try..catch
instrução. Dito isso, uma matriz que contém elementos extremamente heterogêneos parece um problema de design para mim.if ("b" in a && "c" in a.b)
. Pode ser "tedioso", mas é o que você obtém para inconsistência ... lógica normal.Respostas:
Atualização :
Solução para JavaScript anterior ao ECMASCript 2020 ou TypeScript anterior à versão 3.7 :
Uma solução rápida é usar uma função auxiliar try / catch com a função de seta ES6 :
Trecho de trabalho:
Exibir trecho de código
Veja este artigo para detalhes.
fonte
O que você está fazendo levanta uma exceção (e com razão).
Você sempre pode fazer
Mas eu não faria isso, em vez disso, pensaria em seu caso de uso.
Por que você está acessando dados, 6 níveis aninhados que você não conhece? Qual caso de uso justifica isso?
Normalmente, você gostaria de realmente validar o tipo de objeto com o qual está lidando.
Além disso, em uma nota lateral, você não deve usar declarações como
if(a.b)
porque retornará falso se ab for 0 ou mesmo se for "0". Em vez disso, verifique sea.b !== undefined
fonte
typeof a.b === "undefined" && a.b!=null
- desnecessário fazer a segunda parte após a primeira, e faz mais sentido apenas fazerif ("b" in a)
typeof a.b !
== "undefined" && ab! = Null` - observe o!==
Se estou entendendo sua pergunta corretamente, você deseja a maneira mais segura de determinar se um objeto contém uma propriedade.
A maneira mais fácil é usar o
in
operador .Claro que você pode aninhar isso tão profundo quanto quiser
Não tenho certeza se isso ajuda.
fonte
window.b
for indefinido? Você receberá um erro de tipo:Cannot use 'in' operator to search for 'c' in undefined
Se você estiver usando lodash , poderá usar a função "tem". É semelhante ao "in" nativo, mas permite caminhos.
fonte
_.get()
com o padrão para facilitar a leitura:_.get(object, 'a.b.c', 'default');
Experimente isso. Se
a.b
for indefinido, ele deixará aif
instrução sem nenhuma exceção.fonte
Este é um problema comum ao trabalhar com objetos json complexos ou profundos, então tento evitar try / catch ou incorporar várias verificações que tornariam o código ilegível. Normalmente uso esse pequeno pedaço de código em todo o meu processo para fazer o trabalho.
fonte
Se você tem lodash, você pode usar seu
.get
métodoou dê a ele um valor padrão
fonte
Eu uso o undefsafe religiosamente. Ele testa cada nível em seu objeto até obter o valor que você solicitou ou retornar "indefinido". Mas nunca erros.
fonte
_.get
Se você usa o Babel, você já pode usar a sintaxe de encadeamento opcional com o plugin @ babel / plugin-proposal-optional-chaining do Babel . Isso permitiria que você substituísse:
com isso:
fonte
Gosto da resposta de Cao Shouguang, mas não gosto de passar uma função como parâmetro para a função getSafe cada vez que faço a chamada. Eu modifiquei a função getSafe para aceitar parâmetros simples e ES5 puro.
fonte
getSafe(myObj.x.c)
. Tentei as versões mais recentes do Chrome e Firefox.Na resposta de str, o valor 'undefined' será retornado em vez do valor padrão definido se a propriedade for undefined. Isso às vezes pode causar bugs. O seguinte garantirá que defaultVal sempre será retornado quando a propriedade ou o objeto estiver indefinido.
fonte
Lodash possui um
get
método que permite um padrão como um terceiro parâmetro opcional, conforme mostrado abaixo:fonte
Imagine que queremos aplicar uma série de funções
x
se, e somente se,x
não for nulo:Agora, digamos que precisamos fazer o mesmo para
y
:E o mesmo para
z
:Como você pode ver, sem uma abstração adequada, acabaremos duplicando o código continuamente. Essa abstração já existe: a mônada Maybe .
A mônada Maybe contém um valor e um contexto computacional:
Uma implementação ingênua seria assim:
⚠️ Esta implementação é apenas para fins ilustrativos! Não é assim que deve ser feito e está errado em muitos níveis. No entanto, isso deve dar a você uma idéia melhor do que estou falando.
Como você pode ver, nada pode quebrar:
Apêndice 1
Não posso explicar o que são mônadas, pois este não é o propósito deste post e existem pessoas melhores nisso do que eu. No entanto, como Eric Elliot disse em sua postagem em seu blog JavaScript Monads Made Simple :
Apêndice 2
Veja como eu resolveria seu problema usando a mônada Maybe demonetjs
fonte
Eu respondi isso antes e aconteceu de estar fazendo uma verificação semelhante hoje. Uma simplificação para verificar se existe uma propriedade pontilhada aninhada. Você pode modificar isso para retornar o valor ou algum padrão para atingir seu objetivo.
Em sua pergunta, você poderia fazer algo como:
fonte
Eu costumo usar assim:
fonte
Você pode evitar obter um erro fornecendo um valor padrão antes de obter a propriedade
Isso também funciona bem com arrays:
fonte