我正在尝试在node.js中为我的一个小项目创建一个类,但我无法弄清楚范围是如何工作的。
我有一个基本的构造函数:
function testClass(username){
this.config = {
uName : username,
url : 'url_prefix'+username,
};
this.lastGame = {
firstTime : 1,
time : null,
outcome: null,
playingAs: null,
playingAgainst : null,
};
this.loadProfile(this.config['url']);
};
loadProfile函数:
testClass.prototype.loadProfile = function(url){
request(url,function(error,response,body){
$ = cheerio.load(body);
matchTable = $('div[class=test]').children();
tempLast = matchTable.first().html();
if(this.config['firstTime'] == 1 || this.lastGame['time'] != tempLast){
this.lastGame['time'] = tempLast;
}
});
};
(我正在使用Request和Cheerio库。)
我遇到的问题是我无法在“请求”功能中使用“this”来使用类变量
它返回“无法读取未定义的属性'firstTime'。”
这只发生在“请求”功能中。我可以使用“this”及其所有函数/变量就好了。
我已经考虑过将它传递给函数但是a)我找不到如何和b)这意味着我对变量所做的任何修改都不会改变实际的类变量。
有人可以解释一下发生了什么吗?
非常感谢!
答案 0 :(得分:1)
每个function
都会创建一个新范围,因为范围在JavaScript中以函数为中心。 ES6 let
keyword将帮助您规避这种情况。在此之前,您必须坚持保留对您要使用的this
的引用。
testClass.prototype.loadProfile = function(url){
var self = this;
request(url,function(error,response,body){
$ = cheerio.load(body);
matchTable = $('div[class=test]').children();
tempLast = matchTable.first().html();
if(self.config['firstTime'] == 1 || self.lastGame['time'] != tempLast){
self.lastGame['time'] = tempLast;
}
});
};
如果我设置
self.config['time'] = "whatever"
,则this.config['time']
保持不变。
是。这是因为this
引用了request
函数的本地范围,而不是您要引用的loadProfile
范围。这就是您应该使用self
引用而不是this
的原因。 self
在this
的上下文中提到loadProfile
。然后,当您输入this
回调的上下文时,request
已更改。
答案 1 :(得分:1)
典型的解决方案是将this
复制到另一个名为self
的变量中。
但是,如果您不打算创建很多“类”实例,或者它只有一些方法,那么通常更容易避免使用构造函数this
和{{1一共。
new
这使您可以拥有真正的私人数据,而且您不必手动复制function makeAnObject(username){
// declare private information:
var url = 'url_prefix' + username;
// return public information (usually functions):
return {
loadProfile: function(blah) {
// ...
}
};
};
的参数,也不必担心makeOnObject
被破坏,或者记住使用this
等进行前缀调用
答案 2 :(得分:0)
内部请求你有不同的范围。 此内部请求函数可能是请求对象的实例。你可以尝试类似的东西:
testClass.prototype.loadProfile = function(url){
var self = this;
request(url,function(error,response,body){
$ = cheerio.load(body);
matchTable = $('div[class=test]').children();
tempLast = matchTable.first().html();
if(self.config['firstTime'] == 1 || self.lastGame['time'] != tempLast){
self.lastGame['time'] = tempLast;
}
});
};