2017-02-16 1 views
0

Mise à jour Question Titre & description - du 17 Février 2017Comment puis-je Object.assign() valeurs par défaut à un autre objet partiellement complet uniquement pour les propriétés false hasOwnProperty?

Y at-il une fonction efficace qui remplit les propriétés manquantes seulement d'un objet par rapport à un objet de propriétés par défaut et les valeurs?

Je travaille actuellement sur une classe de bot qui récupère une API JSON en mettant à jour des appels Web. Object.assign(targetObj, sourceObj) a beaucoup aidé mais je me demandais s'il y avait une autre méthode comme ça.

function (result) { 
    // default properties if they don't exist inside result object 
    const defaults = { 
     from: { 
      id: NaN, 
      username: "" 
     } 
    }; 

    // Example "from" may not exist at all in the result object. 
    // Maybe "from" does exist in result and provides only an "id", 
    // but I don't want to overwrite the "id" and still provide 
    // the "username" with a default value if there isn't one. 
} 

Je pensais à plusieurs si le conditionnement hasOwnProperty mais je me demande est-il une meilleure façon qu'une table si les conditions comme Object.assign()?

Je ne veux pas exiger un autre script ou utiliser npm pour cela.

+0

La meilleure façon de faire un clone profond est [lodash's _.cloneDeep] (https://lodash.com/docs/4.17.4#cloneDeep) –

Répondre

0

J'ai traversais mes extraits de code et essayer de construire la fonctionnalité que je voulais. J'ai réussi à réussir après plusieurs heures.

Renvoyer un nouvel objet cible sans nuire à l'original.

function defaultsDeep(target, defaults) { 
    var clone = JSON.parse(JSON.stringify(target)); 
    function run(clone, defaults) { 
     const DEFAULTS_PROPERTY_NAMES = Object.getOwnPropertyNames(defaults); 
     DEFAULTS_PROPERTY_NAMES.forEach(function (property) { 
      if (Object.prototype.toString.call(defaults[property]) === "[object Object]") { 
       if (!clone.hasOwnProperty(property)) { 
        clone[property] = {}; 
       } 
       run(clone[property], defaults[property]); 
      } else if (!clone.hasOwnProperty(property)) { 
       clone[property] = defaults[property]; 
      } 
     }); 
    } 
    run(clone, defaults); 
    return clone; 
} 

Exemple

var result = { 
    "message_id": 1, 
    "from": { 
     "id": 12345 
    } 
}; 

const defaults = { 
    "from": { 
     "id": null, 
     "username": "" 
    } 
}; 

var newObj = defaultsDeep(result, defaults); 
console.log("newObj " + JSON.stringify(newObj)); 
/* result 
{ 
    "message_id": 1, 
    "from": { 
     "id": 12345, 
     "username": "" 
    } 
} 
*/ 

Je ne sais pas s'il y a une meilleure façon de coder cela. Mais si c'est le cas, n'hésitez pas à modifier. Aussi, si vous vous demandez pourquoi je n'ai pas utilisé la méthode de boucle for in. C'est parce que jslint le décourage maintenant en es6 et je ne pense pas pouvoir désactiver l'avertissement.

0

Comme Julian Soro a dit dans les commentaires, je pense que la meilleure façon de le faire est à travers lodash. Ils ont même une fonction defaultsDeep

https://lodash.com/docs/4.17.4#defaultsDeep

+0

Je pense que c'est exactement ce que je cherche. Y a-t-il une fonction faite par une version non-npm qui effectue la même tâche? Je ne veux pas inclure d'autres bibliothèques dans ma classe, sauf celles intégrées au nœud. – Nova

+0

Si vous utilisez des modules nodaux, vous avez peut-être déjà lodash. J'envisagerais fortement de l'utiliser. Ce n'est pas si grand et contient beaucoup de fonctions utiles qui sont très utiles –