Accéder dynamiquement à la propriété d'objet à l'aide d'une variable

J'essaie d'accéder à une propriété d'un objet en utilisant un nom dynamique. Est-ce possible?

const something = { bar: "Foobar!" }; const foo = 'bar'; something.foo; // The idea is to access something.bar, getting "Foobar!" 

Il existe deux façons d'accéder aux propriétés d'un objet:

  • Dot notation: something.bar .
  • Notation de support: something['bar'] .

La valeur entre parenthèses peut être une expression quelconque. Par conséquent, si le nom de la propriété est stocké dans une variable, vous devez utiliser la notation de bracket:

 const foo = 'bar'; something[foo]; 

En javascript, nous pouvons accéder avec:

  • Notation par points – foo.bar
  • foo[someVar]foo[someVar] ou foo["string"]

Mais seul un deuxième cas permet d'accéder dynamiquement aux propriétés:

 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 

Voici un exemple ES6 de la façon dont vous pouvez accéder à la propriété d'un objet en utilisant un nom de propriété qui a été généré dynamiquement en concaténant deux chaînes.

 var suffix = " name"; var person = { ["first" + suffix]: "Nicholas", ["last" + suffix]: "Zakas" }; console.log(person["first name"]); // "Nicholas" console.log(person["last name"]); // "Zakas" 

C'est ce qu'on appelle le nom de propriété calculée

Vous pouvez le faire de différentes façons.

 let foo = { bar: 'Hello World' }; foo.bar; foo['bar']; 

La notation de bracket est particulièrement puissante car elle permet d'accéder à une propriété en fonction d'une variable:

 let foo = { bar: 'Hello World' }; let prop = 'bar'; foo[prop]; 

Cela peut être étendu à la mise en boucle de chaque propriété d'un objet. Cela peut sembler redondant en raison des constructions JavaScript plus récentes telles que pour … de …, mais aide à illustrer un cas d'utilisation:

 let foo = { bar: 'Hello World', baz: 'How are you doing?', last: 'Quite alright' }; for (let prop in foo.getOwnPropertyNames()) { console.log(foo[prop]); } 

La notation des points et des brackets fonctionne également comme prévu pour les objets imbriqués:

 let foo = { bar: { baz: 'Hello World' } }; foo.bar.baz; foo['bar']['baz']; foo.bar['baz']; foo['bar'].baz; 

Déconstruction de l'objet

Nous pourrions également considérer la déconstruction de l'objet comme un moyen d'accéder à une propriété dans un objet, mais comme suit:

 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' 

Il devient intéressant quand vous devez également passer des paramètres à cette fonction.

Code 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 

Vous devez utiliser JSON.parse , consultez 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) 

C'est ma solution:

 resolve(path, obj) { return path.split('.').reduce(function(prev, curr) { return prev ? prev[curr] : null }, obj || self) } 

Exemples d'utilisation:

 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'}) 

METTRE À JOUR

J'ai pris en compte les commentaires ci-dessous et je l'ai convenu. Eval doit être évité.

L'accès aux propriétés de la racine dans l'objet est facilement réalisé avec obj[variable] , mais l'embauche complique la chose. Pour ne pas écrire de code déjà écrit, je suggère d'utiliser lodash.get .

Exemple

 // Accessing root property var rootProp = 'rootPropert'; _.get(object, rootProp, defaultValue); // Accessing nested property var listOfNestedProperties = [var1, var2]; _.get(object, listOfNestedProperties); 

Lodash get peut être utilisé de différentes façons, voici un lien vers la documentation lodash.get


Ancienne réponse

L'accès à la propriété imbriquée peut avoir des problèmes comme l' object['key'] .

Vous pouvez utiliser eval() pour accéder aux propriétés imbriquées et non imbriquées ou même pour créer une référence.

 var obj = {firstLevel: 1, nested: {test: 2}}; console.log(eval('obj.firstLevel')); // 1 console.log(eval('obj.nested.test')); // 2 // creating reference var ref = eval('obj.nested'); console.log(ref === obj.nested); // true ref.newProperty = 3; console.log(eval('obj.nested.newProperty')); // 3 

Si votre objet n'aura pas de propriétés imbriquées, je suggérerais d'utiliser [] , sinon, eval() est une option meilleure.

PS

Vous pouvez utiliser eval() également pour définir la valeur.

 var newObj = {value: 1, nested: {value: 0}}; eval('newObj.value = 5'); eval('newObj.nested.value = 10'); console.log(newObj.value); console.log(newObj.nested.value); 

Const something = {bar: "Foobar!" }; Const foo = 'bar';

Quelque chose [`$ {foo}`];

Voici une méthode pour obtenir une propriété ou un objet imbriqué à partir d'un objet utilisant la notation de chemin. C'est une adaptation d'une question similaire à laquelle ont répondu «Prusprus» en 2014.

J'ai un fichier de configuration avec des tableaux imbriqués et je souhaite accéder aux données d'une page Web en envoyant un chemin sous la forme:

"Unit_cfg [2] .chn_cfg [7] .chn_type"

Cette fonction renverra une propriété unique ou un objet. Oui, il peut être simplifié …

 function fetchFromObject(obj: Object, path: string): boolean | Object { var dot_idx: number; var lbkt_idx: number; var rbkt_idx: number; var prop: string; var prop_idx: number; var new_obj: Object; var new_path: string; // Return if no object. if (typeof obj === 'undefined') { return false; } // Get index of first left bracket in path. lbkt_idx = path.indexOf('['); // If left bracket. if (lbkt_idx > -1) { // Get right bracket index. rbkt_idx = path.indexOf(']'); } // Get index of first dot in path. dot_idx = path.indexOf('.'); /* * Most complicated situation is if there are both brackets * and dots in the path. This means we have a mixture of both * indexed and non-indexed properties: * * x[].y --or-- xy[] * * In this case, we must see if the indexed property is before * or after the non-indexed property. * * In either case, we must recurse. */ if ((lbkt_idx > -1) && (dot_idx > -1)) { // If bracket is before dot: x[].y if (lbkt_idx < dot_idx) { // Get property string. prop = path.substr(0, lbkt_idx); // Get index. prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx)); // Get path to right of dot. new_path = path.substr(dot_idx + 1); // Get new object. new_obj = obj[prop][prop_idx]; // Recurse. return fetchFromObject(new_obj, new_path); } // Else dot before bracket: xy[] else { // Get property string. prop = path.substr(0, dot_idx); // Get path to right of dot. new_path = path.substr(dot_idx + 1); // Get new object. new_obj = obj[prop]; // Recurse. return fetchFromObject(new_obj, new_path); } } /* * Else recurse if dotted property; xy */ else if (dot_idx > -1) { // Get property string. prop = path.substr(0, dot_idx); // Get path to right of dot. new_path = path.substr(dot_idx + 1); // Get new object. new_obj = obj[prop]; // Recurse. return fetchFromObject(new_obj, new_path); } /* * Else done if single indexed property: x[] */ else if (lbkt_idx > -1) { // Get property string. prop = path.substr(0, lbkt_idx); // Get index. prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx)); // Return with object. return obj[prop][prop_idx]; } /* * Else single non-indexed property. */ return obj[path]; 

}