Лодаш изменяет первый аргумент, а не создает совершенно новый объект.Каждый из последующих аргументов применяется поверх первого аргумента по порядку, но они сами не затрагиваются.
Мы можем продемонстрировать это, создав функцию установки JavaScript.Это вызывается каждый раз, когда свойство установлено (таким образом, это имя).
let merge1 = { val: 1 };
let merge2 = { val: 2 };
let merge3 = { val: 3 };
let mergeTarget = {
val:0,
set val(name) {
console.log("Setting with:" + name);
}
}
_.merge(mergeTarget,merge1,merge2, merge3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Вы увидите, что установщик на mergeTarget
вызывается не один, а три раза с каждым из следующих свойств в следующем порядке:
Setting with:1
Setting with:2
Setting with:3
Чтобы быть понятным, Lodash действительно возвращает ссылку на конечное значение, что может быть полезно в таких случаях, как при использовании встроенного слияния.Например (для использования надуманного примера):
someArray.map(_.merge(mappingFunction, properties))
Однако, как вы заметили, это возвращаемое значение является просто ссылкой на первый аргумент, который был видоизменен.
Почему?
Что касается более глубокого вопроса , почему lodash делает это так ... Это хороший вопрос, поскольку, как правило, обычно имеет смысл избегать нечистых функций дляпростая служебная функция.На самом деле нужно было бы спросить разработчиков lodash, а также разработчиков подчеркивания, которые устанавливали эту практику.
Но мы можем довольно легко придумать несколько веских причин, почему это было реализовано таким образом и почему оно остается.
1.Простота использования / стиль.
Частью привлекательности Lodash / подчеркивания является то, что они предоставляют удобные и четко определенные служебные функции, которыми легко пользоваться свободно.В той степени, в которой они могут чувствовать себя синтаксическим сахаром для самого JavaScript.В случае, когда вам просто нужно объединить объект, вам нужно беспокоиться или помешать коду, чтобы сделать это следующим образом.
Например, вы можете сделать это:
myComponent.updateConfig = function(update){
_.merge(myComponent.config, update)
}
Какойпросто немного аккуратнее, чем беспокоиться о возвращаемом значении.А учитывая, что побочные эффекты ясны и хорошо определены, использовать его вот так неплохо.
Однако это, пожалуй, наименее важная причина.
2.Производительность.
Разумно по умолчанию избегать создания лишних объектов без необходимости.
Поведение JavaScript по умолчанию состоит в том, чтобы передавать объекты по ссылке, и это не требует какого-либо умного способа сделать мутацию копирования при записи только части объекта.Если вам нужно создать измененную копию объекта, оставив оригинал нетронутым, единственный способ сделать это - скопировать весь объект, а затем внести изменения в копию.
Это не проблема при работе с простыми объектами, имеющими только несколько свойств, но, скажем, у вас есть сложный объект с несколькими сотнями свойств, и вы постепенно объединяете дополнения как часть цикла обновления приложения (дляпример).Нетрудно представить ситуации, когда оптимизация и утечки памяти могут стать проблемой.
3.Легко избежать.
Бывают ситуации, когда нежелательно мутировать объект, и мы предпочли бы чисто функциональное поведение.Однако это легко создать, просто передав в качестве первого параметра пустой объект.
const x = { val: 1 };
const y = { val: 2 };
const z = { val: 3 };
const result = _.merge({},x,y,z);
console.log(x.val) //will return 1
result.val = 5
console.log(x.val) //will still return 1