20

注:この質問は、問題をうまく解決するのに役立つと確信しているので、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},
    }
}

接続されたユーザーには複数の役割があります。その例では である可能性があり、これから、すべてのユーザー ロールで定義されたすべての props の組み合わせとなる['role1', 'role2']単一のオブジェクトを構築する必要があります。permissions

これは基本的にホワイトリスト ベースであり、すべての「true」プロパティが false として定義されたものをオーバーライドする必要があります。したがって、期待される結果は次のようになります。

permissions = {
    views: {
        v1: {access: true},
        v2: {access: true},
        v2: {access: true}
    }
}

クレイジーなネストされたループに頼らずにそれに取り組む方法がよくわかりません

JSBin の開始点は次のとおりです: http://jsbin.com/usaQejOJ/1/edit?js,console

ご協力いただきありがとうございます!

4

2 に答える 2

42

Lodash には、この問題をエレガントに解決するのに役立ついくつかの方法があります。

まずはmerge方法です。複数のソース オブジェクトを取り、それらのプロパティを再帰的にマージして宛先オブジェクトにします。2 つのオブジェクトが同じプロパティ名を持つ場合、後者の値が前者をオーバーライドします。

これはほとんど私たちが望んでいるものです。ロール オブジェクトを 1 つのオブジェクトにマージします。私たちが望んでいないのは、オーバーライド動作です。true値は常に値を上書きする必要がありますfalsemerge幸いなことに、カスタム マージ関数を渡すことができます。2 つのオブジェクトが同じキーを持つ場合、lodashはそれを使用してマージされた値を計算します。

(後の値でs.をオーバーライドORできるようにする代わりに) 項目を論理的に一緒にするカスタム関数を作成して、いずれかの値が の場合、マージされた結果の値が になるようにします。falsetruetruetrue

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 は、もう 1 つの方法で役立ちます_.merge。オブジェクトの配列を一緒にマージすることを受け入れないドキュメントから気付くかもしれません。それらを引数として渡す必要があります。ただし、私たちの場合、配列は非常に便利です。

これを回避するにはapply、引数を配列として渡すことでメソッドを呼び出すことができる JavaScript のメソッドと、flatten入れ子になった配列を含む可能性のある配列を受け取り、それをフラット化する Lodash の便利なメソッドを使用[1, [2, 3], [4, 5]][1, 2, 3, 4, 5]ます。

したがって、必要なすべての引数をflattened 配列に集めて、applyそれらをmerge!

オブジェクトが非常に深くネストされている場合、mergerこのように再帰的に呼び出してスタックをオーバーフローさせる可能性がありますが、オブジェクトの場合、これは問題なく機能するはずです。

于 2014-01-17T21:30:35.683 に答える