Ответ 1
В Lodash есть несколько методов, которые помогут элегантно решить эту проблему.
Прежде всего, merge
. Он принимает несколько исходных объектов и рекурсивно объединяет их свойства в объект назначения. Если два объекта имеют одинаковое имя свойства, последнее значение будет переопределять первое.
Это почти то, что мы хотим; он объединит ваши объекты роли в единый объект. То, что мы не хотим, - это переопределение поведения; мы хотим, чтобы значения true
всегда переопределяли теги false
. К счастью, вы можете передать пользовательскую функцию слияния, и lodash merge
будет использовать это для вычисления объединенного значения, когда два объекта имеют один и тот же ключ.
Мы будем писать пользовательскую функцию для логического OR
ваших элементов вместе (вместо того, чтобы позволить более поздним false
значениям переопределять true
s.), так что если любое значение true
, итоговое объединенное значение будет true
.
Поскольку наши объекты вложены, нам нужно убедиться, что наша пользовательская функция слияния делает это только OR
при сравнении логических значений. При сравнении объектов мы хотим выполнить нормальное слияние их свойств (снова используя нашу пользовательскую функцию для слияния). Это выглядит примерно так:
function do_merge(roles) {
// Custom merge function ORs together non-object values, recursively
// calls itself on Objects.
var merger = function (a, b) {
if (_.isObject(a)) {
return _.merge({}, a, b, merger);
} else {
return a || b;
}
};
// Allow roles to be passed to _.merge as an array of arbitrary length
var args = _.flatten([{}, roles, merger]);
return _.merge.apply(_, args);
}
do_merge([role1, role2, role3]);
Lodash помогает другим способом: вы можете заметить из документов, что _.merge
не принимает массив объектов для слияния; вы должны передать их в качестве аргументов. В нашем случае массив был бы ужасно удобным.
Чтобы обойти это, мы будем использовать метод JavaScript apply
, который позволяет вам вызывать метод, передавая его аргументы в виде массива, а Lodash - flatten
, который принимает массив, который может содержать вложенные массивы - например, [1, [2, 3], [4, 5]]
- и выравнивает его на [1, 2, 3, 4, 5]
.
Итак, мы соберем все необходимые нам аргументы в массиве flatten
ed, а затем apply
до merge
!
Если ваши объекты вложены очень глубоко, есть вероятность, что вы переполните стек, вызывающий merger
рекурсивно, как это, но для ваших объектов это должно работать нормально.