[javascript] Lodash-.extend () / .assign () 및 .merge ()의 차이점
답변
방법은 다음 extend
/ assign
대상에-그대로 소스의 각 속성에 대해 값을 복사 작동합니다. 속성 값 자체가 객체 인 경우 속성의 재귀 적 순회가 없습니다. 전체 객체는 소스에서 가져 와서 대상으로 설정됩니다.
merge
작동 방식 은 다음과 같습니다 . 소스의 각 속성에 대해 해당 속성이 개체 자체인지 확인하십시오. 그렇다면 재귀 적으로 내려 가고 하위 객체 속성을 소스에서 대상으로 매핑하십시오. 따라서 기본적으로 객체 계층을 소스에서 대상으로 병합합니다. 에있는 동안 extend
/ assign
,이 소스로부터 목적지까지의 속성의 간단한 수준의 사본입니다.
이 수정을 명확하게하는 간단한 JSBin이 있습니다 :
http://jsbin.com/uXaqIMa/2/edit?js,console
예제에 배열을 포함하는 더 정교한 버전이 있습니다.
http://jsbin.com/uXaqIMa/1/edit?js,console
답변
Lodash 버전 3.10.1
방법 비교
_.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" ]
답변
주의해야 할 또 다른 차이점은 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.
_.defaultsDeep
works like _defaults but like merge will not simply copy objects
and will use recursion instead.
시맨틱 관점에서 이러한 방법을 생각하는 법을 배우면 기존의 가치와 존재하지 않는 가치에 대한 모든 다른 시나리오에 대한 행동을 더 잘 추측 할 수 있다고 생각합니다.
답변
동일한 obj
참조 를 유지하면서 재정의없이 딥 카피를 원할 경우
obj = _.assign(obj, _.merge(obj, [source]))