115 votes

Comment ajouter automatiquement des propriétés à un objet qui n'est pas défini ?

Existe-t-il un moyen simple d'ajouter automatiquement des propriétés aux objets si elles n'existent pas déjà ?

Prenons l'exemple suivant :

var test = {}
test.hello.world = "Hello doesn't exist!"

Cela ne fonctionne pas car hello n'est pas défini.

La raison pour laquelle je pose cette question est que j'ai quelques objets existants pour lesquels je ne sais pas s'ils ont déjà hello ou pas. En fait, j'ai beaucoup de ces objets dans différentes parties de mon code. Il est très ennuyeux de toujours vérifier si hello existe et s'il n'existe pas crée un nouvel objet comme :

var test = {}
if(test.hello === undefined) test.hello = {}
test.hello.world = "Hello World!"

Existe-t-il un moyen de créer automatiquement un objet du type hello dans cet exemple ?

Je veux dire quelque chose comme ça en php :

$test = array();  
$test['hello']['world'] = "Hello world";   
var_dump($test);

Sortie :

array(1) {
  ["hello"] => array(1) {
    ["world"] => string(11) "Hello world"
  }
}

Ok c'est un tableau mais en js arrays c'est le même problème qu'avec les objets.

163voto

xbonez Points 18866
var test = {};
test.hello = test.hello || {};
test.hello.world = "Hello world!";

Si test.hello est indéfini, il est défini comme un objet vide.

Si test.hello a été défini précédemment, il reste inchangé.

var test = {
  hello : {
    foobar : "Hello foobar"
  }
};

test.hello = test.hello || {};
test.hello.world = "Hello World";

console.log(test.hello.foobar); // this is still defined;
console.log(test.hello.world); // as is this.

74voto

DexBG Points 591

Vous pouvez utiliser l'affectation logique nulle (??=) :

var test = {};
(test.hello ??= {}).world ??= "Hello doesn't exist!";

21voto

columbus Points 191

Nouvel objet

myObj = {};

fonction récursive

function addProps(obj, arr, val) {

    if (typeof arr == 'string')
        arr = arr.split(".");

    obj[arr[0]] = obj[arr[0]] || {};

    var tmpObj = obj[arr[0]];

    if (arr.length > 1) {
        arr.shift();
        addProps(tmpObj, arr, val);
    }
    else
        obj[arr[0]] = val;

    return obj;

}

Appelez-le avec une chaîne notée par un point

addProps(myObj, 'sub1.sub2.propA', 1);

ou avec un tableau

addProps(myObj, ['sub1', 'sub2', 'propA'], 1);

et votre objet ressemblera à ceci

myObj = {
  "sub1": {
    "sub2": {
      "propA": 1
    }
  }
};

Cela fonctionne aussi avec les objets non vides !

7voto

Blender Points 114729

Vous ne pourrez pas le faire sans une sorte de fonction, car JavaScript ne dispose pas d'une méthode générique de récupération/récupération des objets (Python, par exemple, dispose de la fonction __getattr__ ). Voici une façon de procéder :

function add_property(object, key, value) {
    var keys = key.split('.');

    while (keys.length > 1) {
        var k = keys.shift();

        if (!object.hasOwnProperty(k)) {
            object[k] = {};
        }

        object = object[k];
    }

    object[keys[0]] = value;
}

Si vous le voulez vraiment, vous pouvez l'ajouter au prototype de Object . Vous pouvez l'appeler comme ça :

> var o = {}
> add_property(o, 'foo.bar.baz', 12)
> o.foo.bar.baz
12

6voto

John Neuhaus Points 653

Voici une version cool avec des proxies :

const myUpsert = (input) => {
    const handler = {
        get: (obj, prop) => {
            obj[prop] = obj[prop] || {};
            return myUpsert(obj[prop]);
        }
    };
    return new Proxy(input, handler);
};

Et tu l'utilises comme ça :

myUpsert(test).hello.world = '42';

Cela ajoutera toutes les propriétés manquantes en tant qu'objets vides, et laissera les propriétés existantes intactes. Il s'agit en fait d'une version proxy de la méthode classique test.hello = test.hello || {} mais beaucoup plus lentement ( Voir l'indice de référence ici .) Mais c'est aussi beaucoup plus agréable à regarder, surtout si vous travaillez à plus d'un niveau de profondeur. Je ne le choisirais pas pour un traitement de données lourd en termes de performances, mais il est probablement assez rapide pour une mise à jour d'état frontale (comme dans Redux).

Notez qu'il y a quelques hypothèses implicites ici :

  1. Les propriétés intermédiaires sont soit des objets, soit inexistantes. Cette méthode s'étrangle si test.hello est une chaîne de caractères, par exemple.
  2. Il faut toujours faire cela tant que l'on utilise le proxy au lieu de l'objet original.

Ces problèmes sont assez facilement atténués si vous ne l'utilisez que dans des contextes bien délimités (comme un corps de réducteur) où il y a peu de chance de retourner accidentellement le proxy, et pas grand chose d'autre que vous voudriez faire avec l'objet.

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