Lodash-różnica między.extend() /.assign () i.merge()
W Lodash Czy ktoś może podać lepsze wyjaśnienie merge i extend / assign.
To proste pytanie, ale odpowiedź mi umyka.
4 answers
Oto jak extend
/assign
działa: dla każdej właściwości w source skopiuj jej wartość AS-is do miejsca docelowego. jeśli same wartości właściwości są obiektami, nie ma rekurencyjnego przejścia ich właściwości. Cały obiekt zostanie pobrany ze źródła i ustawiony do miejsca docelowego.
Oto jak działa merge
: dla każdej właściwości w source sprawdź, czy ta właściwość jest obiektem. Jeśli tak jest, przejdź rekurencyjnie w dół i spróbuj odwzorować właściwości obiektu potomnego ze źródła do miejsca docelowego. Więc zasadniczo łączymy hierarchia obiektów od źródła do miejsca docelowego. While for extend
/assign
, jest to prosta jednopoziomowa Kopia właściwości od źródła do miejsca docelowego.
Oto prosty JSBin, który uczyniłby to krystalicznie czystym: http://jsbin.com/uXaqIMa/2/edit?js, console
Oto bardziej rozbudowana wersja, która zawiera również tablicę w przykładzie: http://jsbin.com/uXaqIMa/1/edit?js, console
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-07 13:38:39
Wersja Lodash 3.10.1
Metody porównywane
_.merge(object, [sources], [customizer], [thisArg])
_.assign(object, [sources], [customizer], [thisArg])
_.extend(object, [sources], [customizer], [thisArg])
_.defaults(object, [sources])
_.defaultsDeep(object, [sources])
Podobieństwa
- żaden z nich nie działa na tablicach, jak można się spodziewać
-
_.extend
jest aliasem dla_.assign
, więc są identyczne
Wszystkie z nich wydają się modyfikować obiekt docelowy (pierwszy argument)
- wszystkie obsługują
null
to samo
Różnice
-
_.defaults
i_.defaultsDeep
przetwarza argumenty w odwrotnej kolejności w porównaniu do innych (choć pierwszy argument jest nadal obiektem docelowym) -
_.merge
i_.defaultsDeep
Scali obiekty potomne, a pozostałe nadpiszą na poziomie głównym - tylko
_.assign
i_.extend
nadpiszą wartośćundefined
Testy
Oni wszyscy obsługują członków u źródła w podobny sposób.
_.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
uchwyty undefined
ale inni o tym zapomną
_.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" }
Wszystkie obsługują null
to samo
_.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 }
Ale tylko _.merge
i _.defaultsDeep
będą scalać obiekty potomne
_.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" }}
I żadna z nich nie połączy tablic wygląda na to, że
_.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" ] }
Wszystkie modyfikują obiekt docelowy
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" }
Żaden naprawdę nie działa zgodnie z oczekiwaniami na tablicach
Uwaga: Jak zauważył @Mistic, Lodash traktuje tablice jako obiekty, w których klucze są indeksem do tablicy.
_.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" ]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 14:55:00
Kolejną różnicą, na którą należy zwrócić uwagę, jest obsługa undefined
wartości:
mergeInto = { a: 1}
toMerge = {a : undefined, b:undefined}
lodash.extend({}, mergeInto, toMerge) // => {a: undefined, b:undefined}
lodash.merge({}, mergeInto, toMerge) // => {a: 1, b:undefined}
Więc merge
nie połączy undefined
wartości do zdefiniowanych wartości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-20 17:24:57
Pomocne może być również rozważenie tego, co robią z semantycznego punktu widzenia:
_.assign
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
merge is like assign but does not assign objects but replicates them instead.
(deep copy)
_.defaults
provides default values for missing values.
so will assign only values for keys that do not exist yet in the source.
_.defaultsDeep
works like _defaults but like merge will not simply copy objects
and will use recursion instead.
Wierzę, że nauka myślenia o tych metodach z semantycznego punktu widzenia pozwoli Ci lepiej "odgadnąć", jakie byłoby zachowanie dla wszystkich różnych scenariuszy istniejących i nieistniejących wartości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-31 07:06:45