0

以下のコードでは、クロージャーを使用して「this」参照を「保存」し、それをコールバックに渡しました。しかし、私は疑問に思っていました、同じことを達成するための代替技術はありますか?

function App()
{   
    this.number = 75;
}

App.prototype.xmlHandler = function(self)
{
    if (this.number == 99) //true at run-time
        console.log("this.number == 99 is true");
    else
        console.log("this.number == 99 is false");

    if (self.number == app.number) //true at run-time
        console.log("self.number == app.number is true");
    else
        console.log("self.number == app.number is false");
};

App.prototype.loadXML = function(url, handler)
{
    var self = this;
    var req = new XMLHttpRequest();
    req.number = 99;
    req.addEventListener("load", function(){handler.call(req, self);}, false);
    req.open('GET', url, true);
    req.send();
};

App.prototype.init = function()
{
    this.loadXML('resources.xml', this.xmlHandler);
};

var app = new App();
app.init();

xmlHandlerメソッドには、基本的に2つの異なる「this」があります(1つはreqオブジェクト用、もう1つはappオブジェクト用)。それで、1つの屋根の下で2つの異なる「this」値を取得するための代替手法はありますか?

4

4 に答える 4

1

クロージャを作成できるユーティリティ関数がありますが、冗長性はありません。

この特定のケースでは、ES5Function.bindメソッドを使用できます(シムは古いブラウザーですぐに利用できます)。

App.prototype.loadXML = function(url, handler) {
    var req = new XMLHttpRequest();
    req.number = 99;
    req.addEventListener("load", handler.bind(this, req), false);
    req.open('GET', url, true);
    req.send();
};

その結果、handler(に等しい)が元の値(つまりオブジェクト)に等しいまま、最初のパラメーターとしてthis.xmlHandler呼び出されます。thisAppreq

厳密に言えば、これは現在のの定義とは逆の方法ですが、オブジェクトをパラメーターとして渡すのではなく、オブジェクトを参照するxmlHandler方が論理的です。次に、その関数は次のように記述されます。thisApp

App.prototype.xmlHandler = function(req, evt) {
    if (req.number == ...) {
        ...
    }
    ...
}

パラメータがどのように利用可能であるかに注意してevtください-渡されたパラメータは、ブラウザによって提供されるすべてのパラメータの前.bind付加されます。

于 2012-12-18T14:51:34.330 に答える
0

一般的に、クロージャに代わるものはありません。

thisバインディングには、そのうちの1つだけが必要な場合は、Functionメソッド(ES5.1でネイティブ、簡単にシマブル)を使用でき.bind()ます。「2つの異なる'this'値」の場合、2番目のコンテキストをパラメーターとして渡す同様の関数を作成する必要がありますが、クロージャーはimhoよりも単純です。

于 2012-12-18T14:05:57.467 に答える
0

実際には、これを機能させる唯一の方法は、クロージャを使用することです。

.loadXML()そうは言っても、あなたのコードを見ると、コンテキストをまったく気にする必要はないと思います。

App.prototype.loadXML = function(url, handler)
{
    var req = new XMLHttpRequest();
    req.number = 99;
    req.addEventListener("load", handler, false);
    req.open('GET', url, true);
    req.send();
};

これにより関数がクリーンアップされるため、本当にやりたいことを.init():内で表現できます。

App.prototype.init = function()
{
    var self = this;

    this.loadXML('resources.xml', function(evt) {
        // this refers to the XMLHttpRequest
        // self refers to the current App instance
        self.xmlHandler(this);
    });
};
于 2012-12-18T14:20:01.957 に答える
0

これはおそらくあなたが探しているものではありません。いずれにせよ、これは「これ」を共有しています。オブジェクト「inner」は「outer」のメソッドになっているため、そのオブジェクト性を保持していませんが、共有しています。

私がここに書いたものよりも具体的なものを探しているなら、私に知らせてください。

<html>
<head>
</head>
<body>
<p id="result1"></p>
<p id="result2"></p>
</body>
<script>

var outer = function(val, obj){

    this['inner'] = obj['inner'];
            this.val = val;
    this.inner('result1')
    this.val2 = 'not 2';
    this.inner('result2');
};
var inner = function(id){
    this.val2 = this.val2 || 2;
    document.getElementById(id).innerHTML = 'this.val='+this.val+'this.val2='+this.val2;

};

new outer('thing', {'inner': inner});
</script>
</html>
于 2012-12-18T15:42:49.993 に答える