Eu tenho uma estrutura de dados como esta:
var someObject = {
'part1' : {
'name': 'Part 1',
'size': '20',
'qty' : '50'
},
'part2' : {
'name': 'Part 2',
'size': '15',
'qty' : '60'
},
'part3' : [
{
'name': 'Part 3A',
'size': '10',
'qty' : '20'
}, {
'name': 'Part 3B',
'size': '5',
'qty' : '20'
}, {
'name': 'Part 3C',
'size': '7.5',
'qty' : '20'
}
]
};
E eu gostaria de acessar os dados usando estas variáveis:
var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";
part1name deve ser preenchido com someObject.part1.name
o valor de "Part 1". A mesma coisa com part2quantity, que preencheu 60.
Existe alguma maneira de conseguir isso com javascript puro ou JQuery?
javascript
jquery
path
nested
Komaruloh
fonte
fonte
var part1name = someObject.part1name;
`#Respostas:
Acabei de fazer isso com base em um código semelhante que já tinha, parece funcionar:
Uso::
Veja uma demonstração de trabalho em http://jsfiddle.net/alnitak/hEsys/
EDIT Alguns notaram que esse código geraria um erro se passasse uma string em que os índices mais à esquerda não correspondam a uma entrada aninhada corretamente dentro do objeto. Esta é uma preocupação válida, mas o IMHO melhor endereçou com um
try / catch
bloco ao chamar, em vez de ter essa função silenciosamente retornarundefined
para um índice inválido.fonte
_.get(object, nestedPropertyString);
'part3[0].name.iDontExist'
. Adicionar uma verificação para ver seo
há um objeto naif in
correção do problema. (Como você faz isso é com você). Veja o violino atualizado: jsfiddle.net/hEsys/418Esta é a solução que eu uso:
Exemplo de uso:
Limitações:
[]
) para índices de matriz - embora a especificação de índices de matriz entre o token do separador (por exemplo,.
) funcione corretamente, como mostrado acima.fonte
_.reduce()
a partir da biblioteca sublinhado ou lodash)self
é provavelmente indefinido aqui. Você quer dizerthis
?Agora isso é suportado pelo lodash usando
_.get(obj, property)
. Vejo https://lodash.com/docs#getExemplo dos documentos:
fonte
_.set(...)
_.get
mostrará o mesmo comportamento de quando nenhuma chave for encontrada no objeto fornecido. por exemplo_.get(null, "foo") -> undefined
,_.get(null, "foo", "bar") -> "bar"
. No entanto, esse comportamento não está definido nos documentos, portanto, sujeitos a alterações.ES6 : Apenas uma linha no Vanila JS (ele retorna nulo se não encontrar, em vez de dar erro):
Ou exemplo:
Com operador de encadeamento opcional :
Para uma função pronta para usar que também reconhece número falso, 0 e negativo e aceita valores padrão como parâmetro:
Exemplo a usar:
Bônus :
Para definir um caminho (solicitado por @ rob-gordon), você pode usar:
Exemplo:
Matriz de acesso com [] :
Exemplo:
fonte
let o = {a:{b:{c:1}}}; let str = 'a.b.c'; str.split('.').splice(0, str.split('.').length - 1).reduce((p,c)=>p&&p[c]||null, o)[str.split('.').slice(-1)] = "some new value";
0
,undefined
enull
valores.{a:{b:{c:0}}}
retorna emnull
vez de0
. Talvez a verificação explícita de nulo ou indefinido resolva esses problemas.(p,c)=>p === undefined || p === null ? undefined : p[c]
Reflect.has(o, k) ? ...
(ES6 Reflect.has ) trabalhado, apesar desetPath
definirá o valor na primeira ocorrência do último seletor. Por exemplo,let o = {}; setPath(o, 'a.a', 0)
resulta em em{a: 0}
vez de{a: {a: 0}}
. veja este post para uma solução.Você teria que analisar a string você mesmo:
Isso exigia que você também definisse índices de matriz com notação de ponto:
Isso facilita a análise.
DEMO
fonte
[]
sintaxe para a sintaxe da propriedade é bastante trivial.while (l > 0 && (obj = obj[current]) && i < l)
, esse código funcionará também para strings sem pontos.Também funciona para matrizes / matrizes dentro do objeto. Defensivo contra valores inválidos.
fonte
usando eval:
wrap para retornar indefinido por erro
http://jsfiddle.net/shanimal/b3xTw/
Por favor, use o bom senso e cautela ao exercer o poder da avaliação. É um pouco como um sabre de luz, se você ativá-lo, há 90% de chance de cortar um membro. Não é para todos.
fonte
Você pode obter um valor de um membro profundo do objeto com notação de ponto sem nenhuma biblioteca JavaScript externa com o seguinte truque simples:
No seu caso para obter valor
part1.name
a partir desomeObject
apenas fazer:Aqui está uma demonstração simples de violino: https://jsfiddle.net/harishanchu/oq5esowf/
fonte
Provavelmente isso nunca verá a luz do dia ... mas aqui está mesmo assim.
[]
sintaxe do suporte por.
.
personagemundefined
)fonte
É um forro com lodash.
Ou melhor ainda ...
Ou versão ES6 com redução ...
Plunkr
fonte
Eu acho que você está pedindo isso:
Você pode estar perguntando isso:
Ambos irão funcionar
Ou talvez você esteja pedindo isso
Finalmente, você pode estar pedindo por isso
fonte
Split
método, mas simsplit
.Aqui, ofereço mais maneiras, que parecem mais rápidas em muitos aspectos:
Opção 1: Dividir a sequência. ou [ou] ou 'ou ", inverta, pule itens vazios.
Opção 2 (a mais rápida de todas, exceto
eval
): Varredura de caracteres de baixo nível (sem regex / split / etc, apenas uma varredura rápida de caracteres). Nota: Este não suporta aspas para índices.Opção 3: ( novo : opção 2 expandida para oferecer suporte a cotações - um pouco mais lenta, mas ainda rápida)
JSPerf: http://jsperf.com/ways-to-dereference-a-delimited-property-string/3
"eval (...)" ainda é rei (o que é desempenho). Se você possui caminhos de propriedade diretamente sob seu controle, não deve haver nenhum problema com o uso de 'eval' (especialmente se a velocidade for desejada). Se estiver puxando caminhos de propriedade "por cima do fio" ( na linha !? Lol: P), sim, use outra coisa para ser seguro. Apenas um idiota diria para nunca usar "eval", pois existem boas razões para usá-lo. Além disso, "é usado no analisador JSON de Doug Crockford ". Se a entrada for segura, não haverá problemas. Use a ferramenta certa para o trabalho certo, é isso.
fonte
Caso alguém esteja visitando esta pergunta em 2017 ou mais tarde e procurando uma maneira fácil de lembrar , aqui está uma publicação elaborada no blog Acessando Objetos Aninhados em JavaScript sem ser enganada por
Não é possível ler a propriedade 'foo' de indefinido erro
Acessar objetos aninhados usando matriz Reduzir
Vamos pegar esta estrutura de exemplo
Para poder acessar matrizes aninhadas, você pode escrever seu próprio utilitário de redução de matrizes.
Há também um excelente tipo de manipulação de typy mínimo de biblioteca que faz tudo isso para você.
Com o typy, seu código ficará assim
Disclaimer: Eu sou o autor deste pacote.
fonte
AngularJS
A abordagem de Speigg é muito organizada e limpa, embora eu tenha encontrado essa resposta ao procurar a solução de acessar as propriedades do escopo AngularJS $ pelo caminho da string e, com uma pequena modificação, ele faz o trabalho:
Basta colocar esta função no seu controlador raiz e usá-la em qualquer escopo filho como este:
fonte
$scope.$eval
uma outra maneira de fazê-lo com AngularJS.Ainda não encontrei um pacote para executar todas as operações com um caminho de string, então acabei escrevendo meu próprio pacote rápido que suporta insert (), get () (com retorno padrão), set () e remove ( ) operações.
Você pode usar notação de ponto, colchetes, índices numéricos, propriedades de números de sequência e teclas com caracteres que não sejam palavras. Uso simples abaixo:
https://www.npmjs.com/package/jsocrud
https://github.com/vertical-knowledge/jsocrud
fonte
Funciona com
fonte
Função simples, permitindo um caminho de string ou array.
OU
fonte
Agora, existe um
npm
módulo para fazer isso: https://github.com/erictrinh/safe-accessExemplo de uso:
fonte
Embora reduzir seja bom, fico surpreso que ninguém tenha usado cada um:
Teste
fonte
a.b.c
gerará uma exceção se não houver propriedadeb
em seu objeto. Se você precisa de algo silenciosamente descartando o caminho-chave errada (que eu não recomendo), você ainda pode substituir o forEach com um presentekeys.forEach((key)=> obj = (obj||{})[key]);
Apenas tive a mesma pergunta recentemente e utilizou com sucesso https://npmjs.org/package/tea-properties, que também
set
aninhava objetos / matrizes:pegue:
conjunto:
fonte
Inspirado na resposta de @ webjay: https://stackoverflow.com/a/46008856/4110122
Eu criei essa função que você pode usar para obter / definir / desabilitar qualquer valor no objeto
Para usá-lo:
fonte
Estou desenvolvendo uma loja on-line com o React. Tentei alterar os valores no objeto de estado copiado para atualizar o estado original com ele no envio. Os exemplos acima não funcionaram para mim, porque a maioria deles muda a estrutura do objeto copiado. Encontrei um exemplo prático da função para acessar e alterar valores das propriedades profundas do objeto aninhado: https://lowrey.me/create-an-object-by-path-in-javascript-2/ Aqui está:
fonte
Com base na resposta de Alnitak .
Embrulhei o polyfill em um cheque e reduzi a função a uma única redução encadeada.
fonte
Se você precisar acessar diferentes chaves aninhadas sem conhecê-las no momento da codificação (será trivial tratá-las), poderá usar o acessador de notação de matriz:
Eles são equivalentes ao acessador de notação de ponto e podem variar em tempo de execução, por exemplo:
é equivalente a
ou
Espero que este endereço sua pergunta ...
EDITAR
Não usarei uma string para manter uma espécie de consulta xpath para acessar um valor de objeto. Como você precisa chamar uma função para analisar a consulta e recuperar o valor, eu seguiria outro caminho (não:
ou, se você estiver preocupado com o método apply
As funções são mais curtas e claras, o intérprete verifica se há erros de sintaxe e assim por diante.
A propósito, acho que uma tarefa simples feita no momento certo será suficiente ...
fonte
As soluções aqui são apenas para acessar as chaves profundamente aninhadas. Eu precisava de um para acessar, adicionar, modificar e excluir as chaves. Isto é o que eu vim com:
path_to_key
: caminho em uma matriz. Você pode substituí-lo pelo seustring_path.split(".")
.type_of_function
: 0 para acessar (não passe nenhum valor paravalue
), 0 para adicionar e modificar. 1 para excluir.fonte
Partindo da resposta de Alnitak:
}
Isso permite que você defina um valor também!
Eu criei um pacote npm e github com isso também
fonte
Em vez de uma string, uma matriz pode ser usada para endereçar objetos e matrizes aninhados, por exemplo:
["my_field", "another_field", 0, "last_field", 10]
Aqui está um exemplo que alteraria um campo com base nessa representação de matriz. Estou usando algo parecido no react.js para campos de entrada controlada que alteram o estado das estruturas aninhadas.
fonte
Com base em uma resposta anterior, criei uma função que também pode lidar com colchetes. Mas não há pontos dentro deles devido à divisão.
fonte
fonte
Trabalhando com
Underscore
'sproperty
oupropertyOf
:Boa sorte...
fonte