145 votes

Définir dynamiquement la propriété d'un objet imbriqué

J'ai un objet qui pourrait être de n'importe quel niveau de profondeur et pourrait avoir n'importe quelles propriétés existantes. Par exemple:

var obj = {
    db: {
        mongodb: {
            host: 'localhost'
        }
    }
};

Sur cela, j'aimerais définir (ou écraser) des propriétés de cette manière:

set('db.mongodb.user', 'root');
// ou:
set('foo.bar', 'baz');

Où la chaîne de propriété peut avoir n'importe quelle profondeur, et la valeur peut être de n'importe quel type/chose.
Les objets et les tableaux en tant que valeurs n'ont pas besoin d'être fusionnés, si la clé de propriété existe déjà.

L'exemple précédent produirait l'objet suivant:

var obj = {
    db: {
        mongodb: {
            host: 'localhost',
            user: 'root'
        }
    },
    foo: {
        bar: baz
    }
};

Comment puis-je réaliser une telle fonction?

0voto

Gleno Points 59

Amélioration de la réponse de bpmason1 : -ajoute une fonction get(). -Ne nécessite pas de définir un objet de stockage global -Accessible depuis les iFrames du même domaine

function set(path, value) 
{
  var schema = parent.document;
  path="data."+path;
  var pList = path.split('.');
  var len = pList.length;
  for(var i = 0; i < len-1; i++) 
  {
    if(!schema[pList[i]]) 
      schema[pList[i]] = {}
    schema = schema[pList[i]];
  }
  schema[pList[len-1]] = value;
}

function get(path) 
{
  path="data."+path;
  var schema=parent.document;
  var pList = path.split('.');
  for(var i = 0; i < pList.length; i++) 
    schema = schema[pList[i]];
  return schema;
}

set('mongo.db.user', 'root');
set('mongo.db.name', 'glen');

console.log(get('mongo.db.name'));  //affiche 'glen'

0voto

Suraj James Points 1

Parfois, si la clé contient des points (.) dans sa chaîne, cela peut poser un problème. Car même cette seule clé sera maintenant divisée en différentes clés.

Il est préférable de stocker le chemin de la clé dans un tableau, comme ceci : ['db', 'mongodb', 'user'] et d'assigner la valeur dynamiquement avec la fonction ci-dessous.

function set(obj, path, value) {
  var schema = obj;
  var pList = path.slice();
  var len = pList.length;
  for (var i = 0; i < len - 1; i++) {
    var elem = pList[i];
    if (!schema[elem]) schema[elem] = {};
    schema = schema[elem];
  }
  schema[pList[len - 1]] = value;
}

let path = ['db', 'mongodb', 'user'];
set(obj, path, 'root');

0voto

Husdady Points 145

Je veux laisser ma réponse à ce sujet intéressant. Créer une fonction qui définit des propriétés dynamiques pour un objet peut être difficile.

const entity = {
  haveDogs: true,
  dogs: ['Maya', 'Perla']
}

function isObject(obj) {
  return obj instanceof Object && obj.constructor === Object;
}

function setSchema(key, schema, value) {
  if (!isObject(value)) {
    schema[key] = value;
    return
  }

  if (!schema[key]) schema[key] = {}
  schema[key] = mutate(schema[key], value);
}

function mutate(obj, newObjData) {
    const keys = Object.keys(newObjData)

    for (const key of keys) {
      let schema = obj
      const list = key.split('.')
      const value = newObjData[key]
      const total = list.length - 1

      if (list.length === 1) {
        setSchema(key, schema, value)
        continue
      }

      for (let i = 0; i < total; i++) {
        const elem = list[i];
        if (!schema[elem]) schema[elem] = {}
        schema = schema[elem]
      }

      const subField = list[total]
      setSchema(subField, schema, value)
    }

    return obj
}

mutate(entity, {
  haveDogs: false,
  'pet1.pet2.pet3.pet4.pet5': 'pets',
  'bestFriends.list': ['Maya', 'Lucas'],
  friends: {
    'whitelist.permitted': ['Maya', 'Perla'], 
    'party.blocked': ['Juan', 'Trump']
  }
})

console.log('[entity]', entity)

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