Lodashライブラリで、誰かがmergeとextend / assignのより良い説明を提供できますか。
それは簡単な質問ですが、それでも答えは私を回避します。
Lodashライブラリで、誰かがmergeとextend / assignのより良い説明を提供できますか。
それは簡単な質問ですが、それでも答えは私を回避します。
extend/の仕組みは次のassignとおりです。ソースの各プロパティについて、その値をそのままコピー先にコピーします。プロパティ値自体がオブジェクトである場合、それらのプロパティの再帰的なトラバーサルはありません。オブジェクト全体がソースから取得され、宛先に設定されます。
mergeソース内の各プロパティについて、そのプロパティがオブジェクト自体であるかどうかを確認します。その場合は、再帰的にダウンし、子オブジェクトのプロパティをソースから宛先にマップしてみてください。したがって、基本的に、ソースから宛先へのオブジェクト階層をマージします。extend/の場合はassign、ソースから宛先へのプロパティの単純な 1 レベルのコピーです。
これを明確にする単純な 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 ({}, { 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" ]
注意すべきもう 1 つの違いは、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.
セマンティックな観点からこれらのメソッドを考えることを学ぶことで、既存の値と存在しない値のすべての異なるシナリオでどのような動作になるかをよりよく「推測」できるようになると思います。