1

JSONオブジェクトを通過してすべてのサブグループを見つけると思われるこの再帰関数があります。ここに私が持っているものがあります:

var subgroupIds = [];
this.getSubGroups = function (groupId) {
    this.getGroups("groupId="+groupId, function(groups) {
        if ($.isEmptyObject(groups)) {
            return subgroupIds;
        } else {
            $.each(groups, function(index,group) {
            subgroupIds.push(group.id);
                this.getSubGroups(group.id);
            });
        }
    });
}

... getGroups は、すべてのグループを返す非同期関数です。

私の問題は、再帰呼び出しに到達したときに、次のようなエラーが表示されることです。

Uncaught TypeError: Object #<Object> has no method 'getSubGroups' 

スコープの問題だと思いますが、何が問題なのかわかりません。何か案は?

編集:

Bergi が指摘したように、コールバックが必要です。これは私が今持っているものです:

var subgroupIds = [];
var that = this;
this.getSubGroups = function (groupId,callback) {
    this.getGroups("groupId="+groupId, function(groups) {
        if ($.isEmptyObject(groups)) {
            return;
        } else {
            $.each(groups, function(index,group) {
            subgroupIds.push(group.id);
                callback(group.id);
                that.getSubGroups(group.id);
            });
        }
    });
}

問題は、コールバックを呼び出すと、関数が未定義であると表示されることです。

最終的に、サブ group.id の配列を返したいと思います。どうやってそこに着くのかわからない...

4

4 に答える 4

1

これは、で定義された内部関数がクラス/オブジェクトのインスタンスにeach属しておらず、コールバック関数自体を参照しているためです。thisこの問題を回避するために、オブジェクト コンストラクターで次のように記述します。

一般的な解決策:

function SimpleClass() {
     var _this = this;    //Private property, will be shared in all functions defined in the class
     this.value = "Hello";
     this.value2 = " world!";

     function say() {        //private function - use _this (this means something else here)
         return _this.say;   //Gets property of the object
     }
     this.say = function() { //Public function - use this
        alert(this.value+say());  //Here, we can use both this and _this
     }

}

コードの修正:

var _this = this;
var subgroupIds = [];
this.getSubGroups = function (groupId) {
    this.getGroups("groupId="+groupId, function(groups) {
        if ($.isEmptyObject(groups)) {
            return subgroupIds;
        } else {
            $.each(groups, function(index,group) {
            subgroupIds.push(group.id);
                _this.getSubGroups(group.id);
            });
        }
    });
}
于 2013-02-27T21:06:45.927 に答える
1

あなたは以前thisと同じではありません。thisおそらく、最初の呼び出しの前に、this参照しているオブジェクトに関連する変数名に保存し (私はsomeObject... を使用します) 、後でgetSubGroups呼び出しますsomeObject.getSubGroups

var subgroupIds = [];
var someObject = this;
someObject.getSubGroups = function (groupId) {
    this.getGroups("groupId="+groupId, function(groups) {
        if ($.isEmptyObject(groups)) {
            return subgroupIds;
        } else {
            $.each(groups, function(index,group) {
            subgroupIds.push(group.id);
                someObject.getSubGroups(group.id);
            });
        }
    });
}

これが発生する理由は、関数が$.each実装から呼び出されるためです。詳細については、「this」の MDN ドキュメントを参照してください。

于 2013-02-27T21:06:46.893 に答える
1

内部this$.eachコールバックを参照します。次のようなことができます。

var subgroupIds = [];
var self = this;
self.getSubGroups = function (groupId) {
    self.getGroups("groupId="+groupId, function(groups) {
        if ($.isEmptyObject(groups)) {
            return subgroupIds;
        } else {
            $.each(groups, function(index,group) {
            subgroupIds.push(group.id);
                self.getSubGroups(group.id);
            });
        }
    });
}
于 2013-02-27T21:06:52.820 に答える
1

これは、thisが関数レベルで定義されており、この場合内部関数に対して繰り返し処理している配列内の項目にバインドされているためです。 内部関数内では、外部関数内thisと同じものは参照されません。外部レベルで設定し、内部関数内から参照することでthis、これを回避でき ます。var that = this;that

var subgroupIds = [];
var that = this;
this.getSubGroups = function (groupId) {
    this.getGroups("groupId="+groupId, function(groups) {
        if ($.isEmptyObject(groups)) {
            return subgroupIds;
        } else {
            $.each(groups, function(index,group) {
            subgroupIds.push(group.id);
                that.getSubGroups(group.id);
            });
        }
    });
}

詳細については、クロージャの仕組みを参照してください

そして、これがJSでどのように機能するかについては、こちら

于 2013-02-27T21:07:16.820 に答える