我是经验丰富的开发人员,但对java脚本和nodejs不熟悉,如果这个问题已经“按原样”回答,我很抱歉,但即使我已经查看了多个示例和stackoverflow答案,我也没有找到一个简单的完整示例具有正确的'self'var范围和绑定的原型类(this) 我试过了两个都错了......我将感激你的帮助。 我尝试过 var self = this; 在我的函数声明开始时,但是在运行时,它实际上并没有在设置为原型时通过函数代码,因此,'this'设置不正确。
/**
* Module Dependencies
*/
var cheerio = require('cheerio');
var http = require('http');
/**
* Export
*/
module.exports = SimplePageGetter;
function SimplePageGetter(pageLink) {
this._pageLink = pageLink;
}
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
SimplePageGetter.prototype._resultsPageHttpGetCallback = function (response) {
var pageBody = '';
var self = this;
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
self._parsePage(pageBody);
});
};
SimplePageGetter.prototype._parsePage = function (body) {
console.log('page parsed');
}
出于某种原因,调用getPage时'self'是正确的,但是http模块是ClientRequest,而不是_resultsPageHttpGetCallBack上的对象。 我做错了什么?
谢谢,
詹姆斯
答案 0 :(得分:4)
在调用函数中设置self
并没有做任何事情来改变被调用函数中this
的内容。所以看看这个:
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
这仍然只是将对self._resultsPageHttpGetCallback
函数的引用传递给http.request
。 http.request
仍将其称为普通函数,而不是方法,因此this
中的_resultsPageHttpGetCallback
将是未定义的(严格模式)或全局对象(松散模式)。 / p>
self
模式用于在同一作用域(或嵌套作用域)中创建的函数,例如:
function someMethod() {
var self = this;
http.request(self._pageLink, function(err, data) {
// Use `self` here to access object info
}).end();
}
这是有效的,因为我传入http.request
的匿名函数关闭(引用)创建它的上下文,并且该上下文具有self
变量,因此该函数可以访问self
变量。
对于你正在做的事情,Function#bind
会更合适:
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
Function#bind
创建一个 new 函数,在调用时,将调用原始函数,并将this
设置为特定值。
有关this
的更多信息:
this
keyword work? this
仅供参考,以下是应用于完整代码示例的Function#bind
模式:
/**
* Module Dependencies
*/
var cheerio = require('cheerio');
var http = require('http');
/**
* Export
*/
module.exports = SimplePageGetter;
function SimplePageGetter(pageLink) {
this._pageLink = pageLink;
}
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
SimplePageGetter.prototype._resultsPageHttpGetCallback = function (response) {
var pageBody = '';
response.on('data', function (chunk) {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
this._parsePage(pageBody);
}.bind(this));
};
SimplePageGetter.prototype._parsePage = function (body) {
console.log('page parsed');
};
您可以查看ES2015(又名ES6)的新功能,其中许多功能现在可以在v4中使用,因为基础V8引擎支持它们(或者,您可以使用 transpiler 从ES6输入生成ES5代码。
以上是使用ES2015的上述内容:
...箭头函数,它们从定义它们的上下文继承this
,使self
不必要。
... class
关键字,它提供了编写构造函数和原型的更简洁方法。
... let
关键字,因为,您知道,这是ES2015代码。 : - )
应用那些:
/**
* Module Dependencies
*/
let cheerio = require('cheerio');
let http = require('http');
class SimplePageGetter {
constructor(pageLink) {
this._pageLink = pageLink;
}
getPage() {
http.request(this._pageLink, response => {
this._resultsPageHttpGetCallback(response);
}).end();
}
_resultsPageHttpGetCallback(response) {
let pageBody = '';
response.on('data', chunk => {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', () => {
this.parsePage(pageBody);
});
}
_parsePage(body) {
console.log('page parsed');
}
}
/**
* Export
*/
module.exports = SimplePageGetter;
请注意,class
不会像函数声明一样被提升,因此导出的标准位置通常位于模块的底部。如果您只有一个导出(在这种情况下似乎如此),您可以执行
module.exports = class SimplePageGetter {
//...
};
最后但并非最不重要:除非你真的需要_resultsPageHttpGetCallback
和_parsePage
作为对象的属性(这是公共的),否则我可能会改为使用私有函数,它们接受{{ 1}}实例作为标准参数,或者期望使用SimplePageGetter
来调用它,即使它们不是方法。
在这里,他们采取了一个论点:
this
此处,他们希望设置/**
* Module Dependencies
*/
let cheerio = require('cheerio');
let http = require('http');
class SimplePageGetter {
constructor(pageLink) {
this._pageLink = pageLink;
}
getPage() {
http.request(this._pageLink, response => {
resultsPageHttpGetCallback(this, response);
}).end();
}
}
function resultsPageHttpGetCallback(getter, response) {
let pageBody = '';
response.on('data', chunk => {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', () => {
parsePage(getter, pageBody);
});
}
function parsePage(getter, body) {
console.log('page parsed');
}
/**
* Export
*/
module.exports = SimplePageGetter;
,因此我们通过this
调用它们:
Function#call