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 方法下,本质上有两个不同的“this”(一个 [this] 用于 req 对象,另一个 [self] 用于 app 对象)。那么,是否有替代技术可以在一个屋檐下获得两个不同的“this”值?

4

4 回答 4

1

有一些实用函数可以创建一个闭包,但没有冗长。

在这种特殊情况下,您可以使用 ES5Function.bind方法(旧版浏览器可以轻松使用 shims):

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)将被调用,this仍然等于其原始值(即App对象)并req作为第一个参数。

严格来说,这与您当前的定义相反xmlHandler,但恕我直言,this引用App对象而不是将其作为参数传递更合乎逻辑。然后将编写该函数:

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

请注意evt参数是如何可用的 - 传入的参数.bind添加到浏览器提供的任何参数之前。

于 2012-12-18T14:51:34.330 回答
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

一般来说,除了闭包没有其他选择。

对于this绑定,如果您只需要其中一个,可以使用.bind()Function 方法(ES5.1 原生,易于移植)。对于“两个不同的'this'值”,您可能需要编写一个类似的函数,将第二个上下文作为参数传递,但闭包比恕我直言更简单。

于 2012-12-18T14:05:57.467 回答
0

这可能不是您想要的。无论如何,这是共享“这个”。对象“内在”并没有保留其对象性,因为它已成为“外在”的一种方法,但它是共享的。

如果您正在寻找比我在这里写的更具体的东西,请告诉我。

<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 回答