4 votes

Créer un objet avec des sous-objets jusqu'au niveau n

Je possède un objet appelé MyObject et une méthode appelée createEntry() qui vise à créer une nouvelle propriété pour MyObject et des sous-propriétés pour la propriété ou juste la sauter entièrement si elle existe déjà.

Mon code :

var MyObject = {
    createEntry: function (val1, val2, val3, val4) {
        this[val1] = this[val1] || {};
        this[val1][val2] = this[val1][val2] || {};
        this[val1][val2][val3] = val4;
    }
};

MyObject.createEntry("val1", "val2", "val3", "val4");

Comme le montre la fonction ci-dessus, j'essaie de créer un nouveau sous-objet pour chaque argument de la méthode createEntry() sauf pour les deux derniers, où val3 est une propriété ou un méthode et val4 en est la valeur.

Avec ma méthode dans son état actuel, je ne peux atteindre que jusqu'au niveau 3 avec les suivants nécessitant un code de plus en plus long. Je suppose que cela peut être réalisé avec une boucle while, mais je n'ai pas encore trouvé comment le faire.

Question : Comment puis-je créer des sous-objets illimités en fonction du nombre d'arguments passés à la fonction ci-dessus de manière arborescente qui ressemble à ce qui suit :

var MyObject = {
   val1: {
      val2 {
         val3: val4
      }
   }
}

4voto

Oriol Points 20803

reduceRight semble parfait pour cela:

function createEntry(...args) {
  return args.reduceRight(function(prev, curr) {
    return {[curr]: prev};
  });
}
console.log(createEntry("val1", "val2", "val3", "val4"));

1voto

hydroper Points 1

Eh bien, lors de la création d'objets imbriqués illimités en utilisant des paramètres, je itérerai chaque paramètre, en ayant le dernier objet que j'ai entré comme référence. Ce code est suffisant pour comprendre.

Remarque: Object.assign est une nouvelle implémentation de navigateur, mais il existe déjà des polyfills. J'utilise cette méthode pour concaténer un objet avec un autre lorsque un nom d'entrée existe déjà dans un objet

Object['prototype']['createEntries'] = function() {
    /* stocker l'emplacement du dernier objet */
    var lastObj = this

    /**
     * Remarque: chaque argument est un objet qui spécifie les propriétés suivantes -->
     * inner : l'objet d'entrée
     * *name : le nom de la propriété d'entrée
     */

   for (var i = 0, arg, existent, len = arguments.length; i < len; ++i) {
       if (typeof (arg = arguments[i]) === 'object' && (typeof arg.inner === 'object' ? true : arg.inner = {} ))
            /* créer une nouvelle entrée/garder l'entrée existante et la réserver dans lastObj */
            lastObj = (typeof (existent = lastObj[arg.name]) === 'object' ?
                    lastObj[arg.name] = Object.assign(existent, arg.inner) :
                    lastObj[arg.name] = arg.inner)
   }

   return this
}

Ensuite, voici une utilisation de base

({}).createEntries({
    name: "val1"
}, {
    name: "val2"
})
/* {
        val1: {
            val2: {
            }
        }
    }
*/

J'espère que c'est ce que vous voulez

0voto

Angel Politis Points 7101

Oriol a donné une réponse fantastique, mais sa fonction, en raison de sa construction, n'est pas vraiment utile car elle renvoie un nouvel objet au lieu de modifier MyObject.

Donc, pour réellement modifier MyObject, au lieu du premier return, nous devons faire quelque chose d'autre qui modifiera MyObject sans l'écraser.

Pour faire cela, une fonction qui étend le MyObject doit être construite:

expand: function (objet) {
   for (var clé in objet) if (!!objet[clé]) {
      if (clé in this) throw new Error("`" + clé + "` existe déjà.");
      else this[clé] = objet[clé];
   }
}

Ensuite, tout ce que nous avons à faire est d'utiliser la réponse de @Oriol sans la première déclaration return en tant qu'argument de expand():

createEntry: function () {
   this.expand([].reduceRight.call(arguments, function(précédent, actuel) {
      return {[actuel]: précédent};
   }));
}

Code complet :

var MyObject = {
  createEntry: function() {
    this.expand([].reduceRight.call(arguments, function(précédent, actuel) {
      return {
        [actuel]: précédent
      };
    }));
  },
  expand: function(objet) {
    for (var clé in objet)
      if (!!objet[clé]) {
        if (clé in this) throw new Error("`" + clé + "` existe déjà.");
        else this[clé] = objet[clé];
      }
  }
};

MyObject.createEntry("val1", "val2", "val3", "val4");
console.log(MyObject);

Merci à tous pour l'aide!

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