Estou tentando acessar uma propriedade de um objeto usando um nome dinâmico. Isso é possível?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
Estou tentando acessar uma propriedade de um objeto usando um nome dinâmico. Isso é possível?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
Respostas:
Existem duas maneiras de acessar propriedades de um objeto:
something.bar
something['bar']
O valor entre colchetes pode ser qualquer expressão. Portanto, se o nome da propriedade estiver armazenado em uma variável, você precisará usar a notação de colchete:
var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected
Esta é a minha solução:
function resolve(path, obj) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : null
}, obj || self)
}
Exemplos de uso:
resolve("document.body.style.width")
// or
resolve("style.width", document.body)
// or even use array indexes
// (someObject has been defined in the question)
resolve("part.0.size", someObject)
// returns null when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})
Em javascript, podemos acessar com:
foo.bar
foo[someVar]
oufoo["string"]
Mas apenas o segundo caso permite acessar propriedades dinamicamente:
var foo = { pName1 : 1, pName2 : [1, {foo : bar }, 3] , ...}
var name = "pName"
var num = 1;
foo[name + num]; // 1
// --
var a = 2;
var b = 1;
var c = "foo";
foo[name + a][b][c]; // bar
A seguir, é apresentado um exemplo do ES6 de como você pode acessar a propriedade de um objeto usando um nome de propriedade que foi gerado dinamicamente pela concatenação de duas cadeias.
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
Isso é chamado de nomes de propriedades computados
Você pode conseguir isso de várias maneiras diferentes.
let foo = {
bar: 'Hello World'
};
foo.bar;
foo['bar'];
A notação de colchete é especialmente poderosa, pois permite acessar uma propriedade com base em uma variável:
let foo = {
bar: 'Hello World'
};
let prop = 'bar';
foo[prop];
Isso pode ser estendido ao loop sobre todas as propriedades de um objeto. Isso pode parecer redundante devido a construções JavaScript mais recentes, como para ... de ..., mas ajuda a ilustrar um caso de uso:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
for (let prop in foo.getOwnPropertyNames()) {
console.log(foo[prop]);
}
A notação de ponto e colchete também funciona conforme o esperado para objetos aninhados:
let foo = {
bar: {
baz: 'Hello World'
}
};
foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;
Destruição de objetos
Também podemos considerar a destruição de objetos como um meio de acessar uma propriedade em um objeto, mas da seguinte maneira:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
let prop = 'last';
let { bar, baz, [prop]: customName } = foo;
// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'
Você pode fazer isso usando o Lodash get
_.get(object, 'a[0].b.c');
Levei em consideração os comentários abaixo e concordei. Eval deve ser evitado.
O acesso às propriedades raiz no objeto é facilmente alcançado obj[variable]
, mas ficar aninhado complica as coisas. Para não escrever código já escrito, sugiro usar lodash.get
.
Exemplo
// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);
// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);
O Lodash get pode ser usado de diferentes maneiras. Aqui está o link para a documentação lodash.get
eval
sempre que possível. stackoverflow.com/questions/86513/…
eval
algo tão trivial quanto acessar propriedades é um exagero e dificilmente aconselhável sob nenhuma circunstância. O que é "problema"? obj['nested']['test']
funciona muito bem e não requer que você incorpore código em strings.
obj['nested']['value']
- lembre-se crianças, eval é mau!
_.get
para a mesa. Penso que esta resposta merece agora votos em vez de votos negativos. Pode ser um exagero, mas é bom saber que existe.
Sempre que você precisar acessar a propriedade dinamicamente, precisará usar colchetes para acessar a propriedade, não "." operador
Sintaxe: object [propery}
const something = { bar: "Foobar!" };
const foo = 'bar';
// something.foo; -- not correct way at it is expecting foo as proprty in something={ foo: "value"};
// correct way is something[foo]
alert( something[foo])
Me deparei com um caso em que achava que queria passar o "endereço" de uma propriedade de objeto como dados para outra função e preencher o objeto (com AJAX), pesquisar na matriz de endereços e exibir nessa outra função. Eu não poderia usar a notação de ponto sem fazer acrobacias de string, então pensei que uma matriz poderia ser boa para passar. Acabei fazendo algo diferente de qualquer maneira, mas parecia relacionado a este post.
Aqui está uma amostra de um objeto de arquivo de idioma como o de onde eu queria dados:
const locs = {
"audioPlayer": {
"controls": {
"start": "start",
"stop": "stop"
},
"heading": "Use controls to start and stop audio."
}
}
Eu queria poder transmitir uma matriz como: ["audioPlayer", "controls", "stop"] para acessar o texto do idioma, "stop" neste caso.
Eu criei essa pequena função que consulta o parâmetro de endereço "menos específico" (primeiro) e reatribui o objeto retornado a si mesmo. Então, está pronto para procurar o próximo parâmetro de endereço mais específico, se houver algum.
function getText(selectionArray, obj) {
selectionArray.forEach(key => {
obj = obj[key];
});
return obj;
}
uso:
/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs));
/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs));
Fica interessante quando você também precisa passar parâmetros para essa função.
Código jsfiddle
var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}
var str = "method('p1', 'p2', 'p3');"
var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);
var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
// clean up param begninning
parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
// clean up param end
parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}
obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values
Este simples trecho de código pode verificar a existência de variáveis / valores profundamente aninhados sem precisar verificar cada variável ao longo do caminho ...
var getValue = function( s, context ){
return Function.call( context || null, 'return ' + s )();
}
Ex. - uma matriz de objetos profundamente aninhada:
a = [
{
b : [
{
a : 1,
b : [
{
c : 1,
d : 2 // we want to check for this
}
]
}
]
}
]
Ao invés de :
if(a && a[0] && a[0].b && a[0].b[0] && a[0].b[0].b && a[0].b[0].b[0] && a[0].b[0].b[0].d && a[0].b[0].b[0].d == 2 ) // true
Agora podemos:
if( getValue('a[0].b[0].b[0].d') == 2 ) // true
Felicidades!
Eu fiz uma pergunta que meio que foi duplicada sobre esse tópico há algum tempo, e após uma pesquisa excessiva e vendo muitas informações ausentes que deveriam estar aqui, sinto que tenho algo valioso a acrescentar a este post antigo.
let properyValue = element.style['enter-a-property'];
no entanto, raramente vou nessa rota porque não funciona nos valores de propriedades atribuídos por meio de folhas de estilo. Para dar um exemplo, demonstrarei com um pouco de pseudo-código.
let elem = document.getElementById('someDiv');
let cssProp = elem.style['width'];
Usando o exemplo de código acima; se a propriedade width do elemento div que foi armazenada na variável 'elem' foi estilizada em uma folha de estilo CSS e não estilizada dentro de sua tag HTML, sem dúvida você obterá um valor de retorno de indefinido armazenado dentro da variável cssProp. O valor indefinido ocorre porque, para obter o valor correto, o código escrito em uma folha de estilo CSS precisa ser calculado para obter o valor; você deve usar um método que calcule o valor da propriedade cujo valor esteja na folha de estilos.
function getCssProp(){
let ele = document.getElementById("test");
let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}
W3Schools getComputedValue Doc Isso fornece um bom exemplo e permite que você brinque com ele, no entanto, este link O documento getComputedValue do CSS do Mozilla fala sobre a função getComputedValue em detalhes e deve ser lido por qualquer desenvolvedor que não seja totalmente claro sobre esse assunto.
$(selector).css(property,value)
... recebe e define. É o que eu uso, a única desvantagem é que você conhece o JQuery, mas essa é honestamente uma das muitas boas razões para que todo desenvolvedor Javascript deva aprender o JQuery, isso facilita a vida e oferece métodos como este, que não está disponível com Javascript padrão. Espero que isso ajude alguém !!!
Para quem deseja definir o valor de uma variável aninhada, veja como fazê-lo:
const _ = require('lodash'); //import lodash module
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
Documentação: https://lodash.com/docs/4.17.15#set
Além disso, a documentação se você deseja obter um valor: https://lodash.com/docs/4.17.15#get
Você deve usar JSON.parse
, dê uma olhada em https://www.w3schools.com/js/js_json_parse.asp
const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)
const something = { bar: "Foobar!" };
const foo = 'bar';
something[\`${foo}\`];
foo
já é uma string, então `${foo}`
é exatamente o mesmo que foo
. (Além disso, o código parece ter algumas barras invertidas extras que não pertencem lá Mas ainda seria inútil mesmo se você fixa que erro de sintaxe..)