4

ここで精神的に負担のかかる問題が発生しました。Backboneのコレクションを使用してJSONオブジェクトを取得しました。オブジェクトは次のようになります。

{
    "MatchID": "00000001",
    "Date": "1970-01-01T00:00:00.000Z",
    "OriginalID": "",
    "Stage": {
        "StageNumber": "0",
        "StageType": "Stage Type"
    },
    "Round": {
        "RoundNumber": "0",
        "Name": "Round Name"
    },
    "Leg": "1",
    "HomeTeam": {
        "TeamID": "0",
        "Name": "Home Team Name"
    },
    "AwayTeam": {
        "TeamID": "0",
        "Name": "Away Team Name"
    },
    "Venue": {
        "VenueID": "0",
        "Name": "Venu Name"
    },
    "Referee": null,
}

このデータでやりたいのは、Venue.Name属性やDate属性(オブジェクトの深さが異なり、他のデータの場合は2レベルより深くなる可能性がある)などの特定の属性に基づいてフィルター処理することです。 。バックボーンコレクション内に次のコードがあり、コンテンツを適切にフィルタリングして新しいコレクションをフィルタリングして返します。

findWhere: function (Attribute, Value)
{
    return new Project.Collections.Fixtures(this.filter(function (fixture)
    {
        return eval('fixture.attributes.' + Attribute) == Value;
    }));
}

これにより、オブジェクトの任意の深さに対して、フィルタリングする属性と、それに等しくする属性を属性で指定できます。問題は、これを行うために「eval」を使用したくないということですが、「AwayTeam.TeamID」のようなものには機能しないため、明らかに「[Attribute]」を使用できません。

evalを使用せずにこの機能を実現するために使用できる方法を知っている人はいますか?

4

4 に答える 4

9

このようなものを使用すると、オブジェクトの階層をたどって値を見つけることができます。

var x = {
    y: {
        z: 1
    }
};

function findprop(obj, path) {
    var args = path.split('.'), i, l;

    for (i=0, l=args.length; i<l; i++) {
        if (!obj.hasOwnProperty(args[i]))
            return;
        obj = obj[args[i]];
    }

    return obj;
}

findprop(x, 'y.z');

Fixtureこれをメソッドとしてオブジェクトに追加できます。

Fixture = Backbone.Model.extend({
    findprop: function(path) {
        var obj = this.attributes,
            args = path.split('.'), 
            i, l;

        for (i=0, l=args.length; i<l; i++) {
            if (!obj.hasOwnProperty(args[i]))
                return;
            obj = obj[ args[i] ];
        }
        return obj;
    }
});

それを使用して値を抽出します

var f = new Fixture();
f.findprop("HomeTeam.TeamID");

findWhereメソッドは次のように書き直すことができます。

findWhere: function (Attribute, Value)
{
    return new Project.Collections.Fixtures(this.filter(function (fixture){
        return fixture.findprop(Attribute) === Value;
    }));
}

そしてhttp://jsfiddle.net/nikoshr/wjWVJ/3/で遊ぶフィドル

于 2012-05-29T13:14:28.853 に答える
1

JavaScript オブジェクトの属性には、角かっこ、文字列識別子、および標準のドット表記によってアクセスできます。

言い換えれば、これは:

fixture.attributes.something

これと同じです:

fixture.attributes["something"]

変数名を角括弧に渡すこともできます。変数の値は取得するキーとして使用されます。

したがって、コードを次のように変更できます。

findWhere: function (Attribute, Value)
{
    return new Project.Collections.Fixtures(this.filter(function (fixture)
    {
        return fixture.attributes[Attribute] === Value;
    }));
}

コメントで指摘したように、これは 1 つのレベルのオブジェクトと属性のみを処理します。ネストされた属性を取得するには、「属性」変数を分割し、パーツをループする必要があります。そのための@nikoshrのソリューションが好きです。

于 2012-05-29T13:16:43.553 に答える
0

私はnikoshrの答えを取り、それに再帰的な才能を追加しました:

  var findprop = function (obj, path) {
        var args = (typeof path === 'string') ? path.split('.') : path,
            thisProperty = obj[args[0]];
        if (thisProperty === undefined) { return; } //not found

        args.splice(0, 1); //pop this off the array

        if (args.length > 0) { return findprop(thisProperty, args); } //recurse
        else {return thisProperty; }
    };

再帰 CPU にサイクル単位で大きなメリットがあるかどうかはわかりませんが、適切な場合は再帰関数が好きです

于 2012-08-17T15:29:20.410 に答える