Oli*_*ent 20 javascript lodash
注意:我在lodash下提交了这个问题,因为我很确定它可以帮助我很好地解决这个问题,但是现在还没有把它放在它上面
我有一个描述不同用户角色及其权限的对象;
我会像"这样"定义10-15个角色(这不反映应用程序代码,但问题本身):
var role1 = {
views: {
v1: {access: true},
v2: {access: false},
v#: {access: false}
}
}
var role2 = {
views: {
v1: {access: false},
v2: {access: true},
v3: {access: true},
}
}
Run Code Online (Sandbox Code Playgroud)
连接的用户将具有多个角色; 在那个例子中它可能是['role1', 'role2']
,并且我需要构造一个单独的permissions
对象,它将是所有用户角色中定义的所有道具的组合.
它基本上是基于白名单的,其中所有"真实"属性应该覆盖任何被定义为false的属性.因此,预期结果应该是:
permissions = {
views: {
v1: {access: true},
v2: {access: true},
v2: {access: true}
}
}
Run Code Online (Sandbox Code Playgroud)
我不太确定如何在不依赖疯狂的嵌套循环的情况下解决这个问题
这是JSBin的一个起点:http://jsbin.com/usaQejOJ/1/edit?js,console
谢谢你的帮助!
ada*_*que 42
Lodash有一些方法可以帮助优雅地解决这个问题.
首先,merge
方法.它需要多个源对象,并以递归方式将它们的属性合并到一个目标对象中.如果两个对象具有相同的属性名称,则后一个值将覆盖前者.
这几乎是我们想要的; 它会将您的角色对象合并为一个对象.我们不想要的是覆盖行为; 我们希望true
值始终覆盖它们false
.幸运的是,你可以传入一个自定义合并函数,merge
当两个对象具有相同的键时,lodash 将使用它来计算合并值.
我们将逻辑上的一个自定义函数编写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]);
Run Code Online (Sandbox Code Playgroud)
Lodash以另一种方式提供帮助:您可能会注意到_.merge
不接受一组对象合并在一起的文档; 你必须作为参数传递它们.但在我们的例子中,数组非常方便.
为了解决这个问题,我们将使用JavaScript的apply
方法,它允许您通过将其参数作为数组传递来调用方法,以及Lodash的方便flatten
方法,该方法采用可能包含嵌套数组的数组(如[1, [2, 3], [4, 5]]
- )并将其展平为[1, 2, 3, 4, 5]
.
因此,我们将收集flatten
ed数组中所需的所有参数,然后将apply
它们收集起来merge
!
如果您的对象嵌套的非常深,那么您可能会merger
像这样以递归方式溢出堆栈,但对于您的对象,这应该可以正常工作.