975 votes

Accès à une propriété d'objet dont le nom est calculé dynamiquement

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!"

18voto

shalonteoh Points 418

Vous pouvez procéder de la manière suivante en utilisant Lodash get

_.get(object, 'a[0].b.c');

15voto

Mr Br Points 213

MISE À JOUR

L'accès aux propriétés de la racine d'un objet est facilement réalisable à l'aide de la fonction obj[variable] mais l'imbrication complique les choses. Pour ne pas écrire du 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 manières. lodash.get

11voto

Scotty Jamison Points 2878

Pour accéder à une propriété de manière dynamique, il suffit d'utiliser crochets [] comme suit :

const something = { bar: "Foobar!" };
const userInput = 'bar';
console.log(something[userInput])

Le problème

Cette solution présente un inconvénient majeur ! (Je suis surpris que d'autres réponses n'aient pas encore soulevé ce point). Souvent, vous ne voulez accéder qu'aux propriétés que vous avez vous-même placées sur cet objet, vous ne voulez pas accéder aux propriétés héritées.

Voici une illustration de cette question. Nous avons ici un programme d'apparence innocente, mais qui présente un bug subtil - pouvez-vous le repérer ?

const agesOfUsers = { sam: 16, sally: 22 }
const username = prompt('Enter a username:')
if (agesOfUsers[username] !== undefined) {
  console.log(`${username} is ${agesOfUsers[username]} years old`)
} else {
  console.log(`${username} is not found`)
}

Lorsque l'on vous demande un nom d'utilisateur, si vous fournissez "toString" comme nom d'utilisateur, vous obtiendrez le message suivant : "toString is function toString() { [code natif] } years old". Le problème est que agesOfUsers est un objet et, en tant que tel, hérite automatiquement de certaines propriétés telles que .toString() de la classe Object de base. Vous pouvez regarder aquí pour une liste complète des propriétés dont héritent tous les objets.

Solutions

  1. Utiliser un Structure des données de la carte à la place. Le contenu stocké d'une carte ne souffre pas de problèmes de prototype, et constitue donc une solution propre à ce problème.

    const agesOfUsers = new Map() agesOfUsers.set('sam', 16) agesOfUsers.set('sally', 2) console.log(agesOfUsers.get('sam')) // 16

  2. Utiliser un objet dont le prototype est nul, au lieu du prototype par défaut. Vous pouvez utiliser Object.create(null) pour créer un tel objet. Ce type d'objet ne souffre pas de ces problèmes de prototype, car vous l'avez explicitement créé de manière à ce qu'il n'hérite de rien.

    const agesOfUsers = Object.create(null) agesOfUsers.sam = 16 agesOfUsers.sally = 22; console.log(agesOfUsers['sam']) // 16 console.log(agesOfUsers['toString']) // undefined - toString was not inherited

  3. Vous pouvez utiliser Object.hasOwn(yourObj, attrName) pour vérifier d'abord si la clé dynamique à laquelle vous souhaitez accéder se trouve directement sur l'objet et n'est pas héritée (en savoir plus). aquí ). Il s'agit d'une fonctionnalité relativement récente, il convient donc de vérifier les tables de compatibilité avant de l'intégrer dans votre code. Avant Object.hasOwn(yourObj, attrName) vous obtiendrez le même effet par le biais de la Object.prototype.hasOwnProperty.call(yourObj, attrName) . Parfois, vous pouvez voir du code utilisant yourObj.hasOwnProperty(attrName) également, ce qui fonctionne parfois mais comporte quelques pièges que vous pouvez lire à ce sujet aquí .

    // Try entering the property name "toString", // you'll see it gets handled correctly. const user = { name: 'sam', age: 16 } const propName = prompt('Enter a property name:') if (Object.hasOwn(user, propName)) { console.log(${propName} = ${user[propName]}) } else { console.log(${propName} is not found) }

  4. Si vous savez que la clé que vous essayez d'utiliser ne sera jamais le nom d'une propriété héritée (par exemple, ce sont peut-être des nombres, ou ils ont tous le même préfixe, etc), vous pouvez choisir d'utiliser la solution originale.

10voto

Il suffit de faire ceci :

something[foo]

6voto

Luke Points 181

Je suis tombé sur un cas où Je pensais que Je voulais passer l'"adresse" d'une propriété d'objet comme donnée à une autre fonction et remplir l'objet (avec AJAX), faire une recherche dans le tableau d'adresses et l'afficher dans cette autre fonction. Je ne pouvais pas utiliser la notation par points sans faire des acrobaties avec les chaînes de caractères, alors j'ai pensé qu'un tableau pourrait être intéressant à passer à la place. J'ai fini par faire quelque chose de différent de toute façon, mais cela semble lié à cet article.

Voici un exemple d'objet de fichier de langue comme celui dont je voulais obtenir des données :

const locs = {
  "audioPlayer": {
    "controls": {
      "start": "start",
      "stop": "stop"
    },
    "heading": "Use controls to start and stop audio."
  }
}

Je voulais pouvoir passer un tableau tel que : ["audioPlayer", "controls", "stop"] pour accéder au texte de la langue, "stop" dans ce cas.

J'ai créé cette petite fonction qui recherche le paramètre d'adresse "le moins spécifique" (le premier) et se réattribue l'objet retourné. Elle est ensuite prête à rechercher le paramètre d'adresse le plus spécifique suivant, s'il existe.

function getText(selectionArray, obj) {
  selectionArray.forEach(key => {
    obj = obj[key];
  });
  return obj;
}

l'utilisation :

/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs)); 

/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs));

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X