В библиотеке Lodash кто-то может дать лучшее объяснение merge и продлить/назначить.
Это простой вопрос, но ответ все же уклоняется от меня.
В библиотеке Lodash кто-то может дать лучшее объяснение merge и продлить/назначить.
Это простой вопрос, но ответ все же уклоняется от меня.
Здесь работает extend
/assign
: для каждого свойства в источнике скопируйте его значение as-is в пункт назначения. если сами значения свойств являются объектами, рекурсивный обход их свойств отсутствует. Весь объект будет взят из источника и установлен в пункт назначения.
Вот как работает merge
: для каждого свойства в источнике проверьте, является ли это свойство самим объектом. Если он затем рекурсивно идет вниз и пытается сопоставить свойства дочерних объектов от источника к месту назначения. Таким образом, мы объединим иерархию объектов от источника к месту назначения. Пока для extend
/assign
, это простая одноуровневая копия свойств из источника в пункт назначения.
Здесь простой JSBin, который сделает этот кристалл ясным: http://jsbin.com/uXaqIMa/2/edit?js,console
Здесь более сложная версия, которая также включает массив в примере: 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
это псевдоним для _.assign
, поэтому они идентичныnull
одинаково_.defaults
и _.defaultsDeep
обрабатывают аргументы в обратном порядке по сравнению с другими (хотя первый аргумент все еще является целевым объектом)_.merge
и _.defaultsDeep
объединят дочерние объекты, а остальные перезапишут на корневом уровне._.assign
и _.extend
будут перезаписывать значение с 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
обрабатывает undefined
но остальные _.assign
его_.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
одинаково_.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
и _.defaultsDeep
будут объединять дочерние объекты_.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" }
Примечание. Как указывает @Mistic, Lodash рассматривает массивы как объекты, ключи которых являются индексом в массиве.
_.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" ]
Еще одно отличие, на которое нужно обратить внимание: обработка значений 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}
Итак, merge
не будет объединять значения undefined
в определенные значения.
Также может быть полезно рассмотреть, что они делают с семантической точки зрения:
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.
Я считаю, что научиться думать об этих методах с семантической точки зрения позволит вам лучше "угадать", каково поведение всех сценариев существующих и не существующих значений.
Если вы хотите глубокое копирование без переопределения при сохранении той же ссылки на obj
obj = _.assign(obj, _.merge(obj, [source]))