Jso nnet s +
и std.mergePatch
- это совершенно разные операции. Оператор +
работает только на одном уровне, а std.mergePatch
рекурсивно просматривает объект и объединяет вложенные объекты. Проще всего объяснить на примере:
local foo = { a: {b1: {c1: 42}}},
bar = { a: {b2: {c2: 2}}};
foo + bar
Вывод:
{
"a": {
"b2": {
"c2": 2
}
}
}
Обратите внимание, что bar.a
полностью заменяет foo.a
. С +
все поля во втором объекте имеют приоритет над полями в первом объекте. Сравните это с результатом использования std.mergePatch(foo, bar)
.
{
"a": {
"b1": {
"c1": 42
},
"b2": {
"c2": 2
}
}
}
Поскольку оба foo
и bar
имеют поле a
, объединяется, и окончательные результаты содержат как b1
, так и b2
.
Итак, повторюсь, +
- это «плоская» операция, которая заменяет поля первого объекта полями второго объекта.
Но это не конец истории. Вы упомянули синтаксис field+: value
, и я попытаюсь объяснить, что он на самом деле делает. В Jso nnet +
это не просто перезапись, а наследование в объектно-ориентированном смысле. Он создает объект, который является результатом наследования второго объекта от первого. Это немного экзотично c, чтобы иметь для этого оператор - во всех основных языках такие отношения определены статически. В Jso nnet, когда вы выполняете foo + bar
, объект bar
имеет доступ к материалам от foo
до super
:
{ a: 2 } + { a_plus_1: super.a + 1}
Это приводит к:
{
"a": 2,
"a_plus_1": 3
}
Вы можете использовать эту функцию, чтобы объединить поля глубже:
{ a: {b: {c1: 1}, d: 1}} +
{ a: super.a + {b: {c2: 2} } }
Результат:
{
"a": {
"b": {
"c2": 2
},
"d": 1
}
}
Это немного повторяется (это будет раздражать, если имя поля было длиннее). Итак, у нас есть хороший синтаксический сахар для этого:
{ a: {b: {c1: 1} , d: 1}} +
{ a+: {b: {c2: 2}} }
Обратите внимание, что в этих примерах мы выполняли слияние только для одного выбранного поля. Мы все же заменили значение a.b
. Это гораздо более гибко, потому что во многих случаях вы не можете просто наивно объединить все внутри (иногда вложенный объект - это «atomi c» и его следует полностью заменить).
Версия в +:
работает так же, как и версия с super
. Тонкая разница в том, что +:
фактически переводится во что-то вроде if field in super then super.field + val else val
, поэтому оно также возвращает то же значение, когда super
не указан вообще или не имеет этого конкретного поля. Например, {a +: {b: 42}}
отлично оценивается как {a: { b: 42 }}
.
Обязательная проповедь: хотя +
очень мощный, пожалуйста, не злоупотребляйте им. Если вам нужно что-то параметризовать, подумайте об использовании функций вместо наследования.