所以我正在构建一个Javascript路由器并构建这样的路由:
route('/user/{name}', 'page', function() {
this.text = 'User: ' + this.name;
});
函数的作用域是当前路径,所以我可以在这里操作当前路径(this.text是视图所寻找的)。
现在我的下一步是在路线中包含一个XHR请求,如下所示:
route('/user/{name}', 'page', function() {
this.text = 'Loading';
var request = new XMLHttpRequest();
request.open('GET', '/api/user', true);
request.onreadystatechange = (function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.responseText);
// here is the issue: 'this' now refers to
// the XHR request and not the scope of the router
this.age = data.age;
this.gender = data.gender;
} else {
this.text = "Error";
}
}
})/* .bind(this); */ // keeping scope like this overwrites the XHR
request.send();
request = null;
});
这里的问题是我需要访问XHR范围和我路由器的范围。在onreadystatechange末尾使用.bind将覆盖XHR范围,而不是设置它会覆盖路由器的范围。
扫管笏吗?有没有比var that = this;
更清洁的东西 - 肯定有办法吗?
答案 0 :(得分:3)
怎么样:
route('/user/{name}', 'page', function() {
var routeScope = this;
request.onreadystatechange = (function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
console.log(this);
// "this" is xhr's scope, while
console.log(routeScope);
// routeScope is your router's scope
// ...
}
}
});
})
编辑:错误,只读你的最后一句......没关系。
答案 1 :(得分:3)
最简单(也是非常明确的方法)是保持对路径范围的引用,如下所示:
var that = this;
您也可以使用.bind()
设置范围,并直接从reqest
变量访问请求属性。
对于您的示例(使用bind
辅助函数,支持旧浏览器):
var bind = function(fn, context) {
return function() {
fn.apply(context, arguments);
};
};
request.onreadystatechange = bind(function() {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText);
this.age = data.age;
this.gender = data.gender;
} else {
this.text = "Error";
}
}
}, this);