126 votes

Accéder aux propriétés des enfants d'un objet à l'aide d'une chaîne de caractères en notation pointée

Je suis temporairement bloqué avec ce qui semble être un problème JavaScript très simple, mais peut-être qu'il me manque simplement les bons mots-clés de recherche !

Supposons que nous ayons un objet

var r = { a:1, b: {b1:11, b2: 99}};

Il y a plusieurs façons d'accéder au 99 :

r.b.b2
r['b']['b2']

Ce que je veux, c'est pouvoir définir une chaîne de caractères

var s = "b.b2";

puis accéder au 99 en utilisant

r.s or r[s] //(which of course won't work)

Une solution consiste à écrire une fonction qui scinde la chaîne de caractères en points et qui, éventuellement, récupère la propriété de manière récursive/itérative. Mais existe-t-il un moyen plus simple/efficace ? Y a-t-il quelque chose d'utile dans l'une des API de jQuery ?

140voto

Andy E Points 132925

Voici une fonction naïve que j'ai écrite il y a un certain temps, mais qui fonctionne pour les propriétés de base des objets :

function getDescendantProp(obj, desc) {
    var arr = desc.split(".");
    while(arr.length && (obj = obj[arr.shift()]));
    return obj;
}

console.log(getDescendantProp(r, "b.b2"));
//-> 99

Bien qu'il existe des réponses qui étendent cette méthode pour "autoriser" l'accès à l'index des tableaux, ce n'est pas vraiment nécessaire car vous pouvez simplement spécifier des index numériques en utilisant la notation par points avec cette méthode :

getDescendantProp({ a: [ 1, 2, 3 ] }, 'a.2');
//-> 3

133voto

AmmarCSE Points 25530

diviser y réduire tout en transmettant l'objet en tant que initalValue

Mise à jour (grâce au commentaire de TeChn4K)

Avec la syntaxe ES6, il est encore plus court

var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";

var value = s.split('.').reduce((a, b) => a[b], r);

console.log(value);

Ancienne version

var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";

var value = s.split('.').reduce(function(a, b) {
  return a[b];
}, r);

console.log(value);

38voto

Matheus Dal'Pizzol Points 1261

Vous pouvez utiliser Méthodes lodash get() et set() .

Obtenir

var object = { 'a': [{ 'b': { 'c': 3 } }] };

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

Paramètres

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// → 4

22voto

Rory McCrossan Points 69838

S'il est possible, dans votre scénario, de mettre l'ensemble de la variable tableau recherchée dans une chaîne de caractères, vous pouvez utiliser la fonction eval() fonction.

var r = { a:1, b: {b1:11, b2: 99}};
var s = "r.b.b2";
alert(eval(s)); // 99

Je sens que les gens sont horrifiés

20voto

Jason More Points 2745

En complément de la réponse de @JohnB, j'ai également ajouté une valeur setter. Voir le plunkr à

http://plnkr.co/edit/lo0thC?p=preview

enter image description here

function getSetDescendantProp(obj, desc, value) {
  var arr = desc ? desc.split(".") : [];

  while (arr.length && obj) {
    var comp = arr.shift();
    var match = new RegExp("(.+)\\[([0-9]*)\\]").exec(comp);

    // handle arrays
    if ((match !== null) && (match.length == 3)) {
      var arrayData = {
        arrName: match[1],
        arrIndex: match[2]
      };
      if (obj[arrayData.arrName] !== undefined) {
        if (typeof value !== 'undefined' && arr.length === 0) {
          obj[arrayData.arrName][arrayData.arrIndex] = value;
        }
        obj = obj[arrayData.arrName][arrayData.arrIndex];
      } else {
        obj = undefined;
      }

      continue;
    }

    // handle regular things
    if (typeof value !== 'undefined') {
      if (obj[comp] === undefined) {
        obj[comp] = {};
      }

      if (arr.length === 0) {
        obj[comp] = value;
      }
    }

    obj = obj[comp];
  }

  return obj;
}

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