[javascript] Lodash-.extend () / .assign () 및 .merge ()의 차이점

에서 Lodash의 도서관, 캔 누군가가 더 나은 설명이 제공 병합을 하고 / 할당을 확장 .

간단한 질문이지만 대답은 나를 피합니다.



답변

방법은 다음 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]))


답변