我有问题仍然困扰我js oop - 我确定我做得不好,但我不能得到如何正确。
例如,我有这段代码
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
this.setToken(token);
this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
问题是我无法从“request.onloadend”函数的上下文访问函数setToken - 这可能是因为我丢失了对“this”的引用。
这是什么问题的解决方案?我可以以某种方式将“this”var传递给此函数的上下文吗?
谢谢!
答案 0 :(得分:5)
有几种方法可以做到这一点。最直接的是简单地保存所需值的副本:
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
var self = this; // save "this" value
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
self.setToken(token); // use saved "this" value
self.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
另一种方法是使用bind
:
request.onloadend = (function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
this.setToken(token); // use saved "this" value
this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}).bind(this);
第二种方法是“更干净”,但它有浏览器兼容性问题(IE< 9不支持它)。
答案 1 :(得分:2)
.bind
功能:
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
this.setToken(token);
this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}.bind(this); //<-- bound
}
答案 2 :(得分:1)
你可以在外部范围内捕获对它的引用,我使用了标识符self
,但是请随意给这个名称更多的语义含义:
var self = this;
request.onloadend = function () {
...
self.setToken(token);
...
};
答案 3 :(得分:1)
在回调之前捕获this
:
Auth.prototype.auth = function () {
var self = this;
var request = new XMLHttpRequest();
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
self.setToken(token);
self.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
答案 4 :(得分:0)
将this
保存在回调之外的本地var中。
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
var _this = this;
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
_this.setToken(token);
_this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
答案 5 :(得分:0)
你是对的:使用XMLHTTPRequest
对象作为上下文(即this
的值)调用回调。您需要为实例指定另一个名称,以便可以在回调范围内访问它:
Auth.prototype.auth = function () {
var request = new XMLHttpRequest(),
authInstance = this;
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
authInstance.setToken(token);
authInstance.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
See this answer to another question for more explanation of why this is necessary。我使用authInstance
而不是self
,因为我认为使用描述性变量名称通常很好;你永远不会知道authInstance
意味着什么,而self
可能是未来某人(可能是你!)读取代码时的模糊不清。
另一种选择是使用bind
,但这可能比这里更复杂。