web-dev-qa-db-fra.com

Récursif / profond étendre / assigner dans Underscore.js?

Existe-t-il un moyen d'obtenir Underscore.js extend fonction:

Copiez toutes les propriétés des objets source vers l'objet de destination et renvoyez l'objet de destination. C'est dans l'ordre, donc la dernière source remplacera les propriétés du même nom dans les arguments précédents.

... pour travailler récursivement?

En fait, la propriété query dans creditOperation va remplacer complètement la propriété query définie dans baseOperation:

var url = require('url')
  , _ = require('underscore'),
  , baseOperation = {
        Host: 'gateway.skebby.it',
        pathname: 'api/send/smseasy/advanced/http.php',
        protocol: 'https',
        query: {
            'username': 'foo',
            'password': 'bar',
        }
    };

var creditOperation = _.extend(baseOperation, {
    query: {
        'method': 'baz'
    }
});

console.log(url.format(creditOperation));

J'aimerais obtenir ce creditOperation:

{
    Host: 'gateway.skebby.it',
    pathname: 'api/send/smseasy/advanced/http.php',
    protocol: 'https',
    query: {
        'username': 'foo',
        'password': 'bar',
        'method': 'baz'
    }
}
31
gremo

Non, le soulignement ne contiendra pas d'étendue profonde car il est trop compliqué de traiter différents types d'objets. Au lieu de cela, les utilisateurs sont encouragés à mettre en œuvre leurs propres solutions en prenant en charge ce dont ils ont besoin.

Dans votre cas, ce ne sont que des objets simples, donc une implémentation est assez simple:

_.deepObjectExtend = function(target, source) {
    for (var prop in source)
        if (prop in target)
            _.deepObjectExtend(target[prop], source[prop]);
        else
            target[prop] = source[prop];
    return target;
}
20
Bergi

Avec Lodash (fork du trait de soulignement), vous pouvez. La méthode de Lodash _. Extend accepte que le troisième paramètre (ou supérieur) soit une fonction, qui reçoit des valeurs (anciennes et nouvelles); Vous pouvez donc faire quelque chose comme ceci:

var deep = function(a, b) {
    return _.isObject(a) && _.isObject(b) ? _.extend(a, b, deep) : b;
};

var a = {a:{b:{c:1}}},
    b = {a:{b:{z:1}}};

_.extend(a,b,deep);

upd. Comme Paolo Moretti l'a dit dans les commentaires, il y a la même fonction dans lodash appelé _. merge :

_.merge(a,b);
38
gobwas

jQuery a une fonction extend () , qui fait la même chose que son homologue Underscore, mais a également un argument deep qui lui permet de fusionner récursivement comme vous le souhaitez:

var creditOperation = $.extend(true, baseOperation, {
    query: {
        'method': 'baz'
    }
});

Ou, si vous ne voulez pas écraser baseOperation:

var creditOperation = $.extend(true, {}, baseOperation, {
    query: {
        'method': 'baz'
    }
});
23
Randy

Version autonome de l'extension profonde de Bergi, y compris le correctif pour quand une valeur est une chaîne au lieu d'un objet. Également patché pour être plus strict.

function deepObjectExtend (target, source) {
    for (var prop in source) {
        if (source.hasOwnProperty(prop)) {
            if (target[prop] && typeof source[prop] === 'object') {
                deepObjectExtend(target[prop], source[prop]);
            }
            else {
                target[prop] = source[prop];
            }
        }
    }
    return target;
}
7
KrekkieD

Kurt Milam a publié un mixin qui ajoute une méthode deepExtend à underscore.js . Il traite même des expressions régulières (si vous le souhaitez). Extrait de la documentation:

Mélangez-le avec underscore.js: _.mixin({deepExtend: deepExtend});

Appelez-le comme ceci: var myObj = _.deepExtend(grandparent, child, grandchild, greatgrandchild)

Remarques: Gardez-le au SEC.

Cette fonction est particulièrement utile si vous travaillez avec des documents de configuration JSON. Il vous permet de créer un document de configuration par défaut avec les paramètres les plus courants, puis de remplacer ces paramètres pour des cas spécifiques. Il accepte n'importe quel nombre d'objets comme arguments, vous donnant un contrôle précis sur la hiérarchie de votre document de configuration.

2
peterp

l'extension () du soulignement ne fait pas d'extension profonde; en fait, il n'y a aucune fonction dans le trait de soulignement qui peut s'étendre profondément.

Vous pouvez utiliser fusion de lodash pour cela.

1
Gaurang Patel