Dans la bibliothèque Lodash , quelqu'un peut-il fournir une meilleure explication de fusion et extend/assign .
C'est une question simple mais la réponse m'échappe néanmoins.
Voici comment extend
/assign
fonctionne: Pour chaque propriété de la source, copiez sa valeur telle quelle dans la destination. Si les valeurs de propriété elles-mêmes sont des objets, il n'y a pas de parcours récursif de leurs propriétés. L'objet entier serait pris à partir de la source et défini dans la destination.
Voici comment merge
fonctionne: Pour chaque propriété de la source, vérifiez si cette propriété est elle-même un objet. Si c'est le cas, descendez récursivement et essayez de mapper les propriétés de l'objet enfant de la source à la destination. Nous fusionnons donc essentiellement la hiérarchie des objets de la source à la destination. Alors que pour extend
/assign
, il s’agit d’une simple copie à un niveau des propriétés de la source à la destination.
Voici un simple JSBin qui rendrait cela très clair: http://jsbin.com/uXaqIMa/2/edit?js,console
Voici une version plus élaborée incluant le tableau dans l'exemple également: http://jsbin.com/uXaqIMa/1/edit?js,console
_.merge(object, [sources], [customizer], [thisArg])
_.assign(object, [sources], [customizer], [thisArg])
_.extend(object, [sources], [customizer], [thisArg])
_.defaults(object, [sources])
_.defaultsDeep(object, [sources])
_.extend
est un alias pour _.assign
, donc ils sont identiquesnull
le même_.defaults
et _.defaultsDeep
traite les arguments dans l'ordre inverse des autres (bien que le premier argument soit toujours l'objet cible)_.merge
et _.defaultsDeep
fusionnent des objets enfants et les autres écrasent au niveau racine._.assign
et _.extend
écraseront une valeur avec undefined
_.assign ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.merge ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.defaults ({}, { a: 'a' }, { a: 'bb' }) // => { a: "a" }
_.defaultsDeep({}, { a: 'a' }, { a: 'bb' }) // => { a: "a" }
_.assign
gère undefined
mais les autres l'ignoreront_.assign ({}, { a: 'a' }, { a: undefined }) // => { a: undefined }
_.merge ({}, { a: 'a' }, { a: undefined }) // => { a: "a" }
_.defaults ({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }
_.defaultsDeep({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }
null
le même_.assign ({}, { a: 'a' }, { a: null }) // => { a: null }
_.merge ({}, { a: 'a' }, { a: null }) // => { a: null }
_.defaults ({}, { a: null }, { a: 'bb' }) // => { a: null }
_.defaultsDeep({}, { a: null }, { a: 'bb' }) // => { a: null }
_.merge
et _.defaultsDeep
fusionneront des objets enfants_.assign ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "b": "bb" }}
_.merge ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}
_.defaults ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a" }}
_.defaultsDeep({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}
_.assign ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.merge ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.defaults ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a" ] }
_.defaultsDeep({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a" ] }
a={a:'a'}; _.assign (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.merge (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaults (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaultsDeep(a, {b:'bb'}); // a => { a: "a", b: "bb" }
Remarque: Comme @Mistic l'a souligné, Lodash considère les tableaux comme des objets dont les clés sont l'index du tableau.
_.assign ([], ['a'], ['bb']) // => [ "bb" ]
_.merge ([], ['a'], ['bb']) // => [ "bb" ]
_.defaults ([], ['a'], ['bb']) // => [ "a" ]
_.defaultsDeep([], ['a'], ['bb']) // => [ "a" ]
_.assign ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.merge ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.defaults ([], ['a','b'], ['bb']) // => [ "a", "b" ]
_.defaultsDeep([], ['a','b'], ['bb']) // => [ "a", "b" ]
Une autre différence à prendre en compte est le traitement des valeurs undefined
:
mergeInto = { a: 1}
toMerge = {a : undefined, b:undefined}
lodash.extend({}, mergeInto, toMerge) // => {a: undefined, b:undefined}
lodash.merge({}, mergeInto, toMerge) // => {a: 1, b:undefined}
Ainsi, merge
ne fusionnera pas les valeurs de undefined
en valeurs définies.
Il pourrait également être utile de considérer ce qu’ils font d’un point de vue sémantique:
will assign the values of the properties of its second parameter and so on,
as properties with the same name of the first parameter. (shallow copy & override)
merge is like assign but does not assign objects but replicates them instead.
(deep copy)
provides default values for missing values.
so will assign only values for keys that do not exist yet in the source.
works like _defaults but like merge will not simply copy objects
and will use recursion instead.
Je pense qu'apprendre à penser à ces méthodes du point de vue sémantique vous permettrait de mieux "deviner" quel serait le comportement pour tous les différents scénarios de valeurs existantes et non existantes.
Si vous voulez une copie en profondeur sans substitution tout en conservant la même référence obj
obj = _.assign(obj, _.merge(obj, [source]))