在下面的代码中,我使用闭包来“保存”“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对象)。那么,是否有其他技术可以在一个屋檐下获得两个不同的“这个”值?
答案 0 :(得分:1)
有一些实用程序函数可以创建一个闭包,但没有详细程度。
在这种特殊情况下,您可以使用ES5 Function.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
)将被调用this
仍然等于其原始值(即App
对象)和以req
作为第一个参数。
严格地说,这与您当前对xmlHandler
的定义相反,但让this
引用App
对象代替它更合乎逻辑的恕我直言作为参数传递。然后写下这个函数:
App.prototype.xmlHandler = function(req, evt) {
if (req.number == ...) {
...
}
...
}
注意evt
参数如何也可用 - .bind
中传递的参数预先到浏览器提供的任何参数。
答案 1 :(得分:0)
一般来说,闭包没有其他选择。
对于this
绑定,如果只需要其中一个,则可以使用.bind()
Function method(ES5.1本机,可轻松缩放)。对于“两个不同的'这个'值”,您可能需要编写一个类似的函数,将第二个上下文作为参数传递,但是闭包比imho更简单。
答案 2 :(得分: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);
});
};
答案 3 :(得分: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>