Javascript 节点js原型对象';自我';var没有为回调存储正确的上下文
我是一名经验丰富的开发人员,但对java脚本和nodejs还不熟悉,如果这个问题的答案是“按原样”的话,我很抱歉,但是尽管我已经阅读了多个示例和stackoverflow的答案,但我没有找到一个具有正确“自”变量范围和绑定的原型类的简单完整示例(此示例)。 我两次都试了,但都出了问题。。。我将感谢你的帮助。 我试着把 var self=这个; 在我的函数声明的开头,但在运行时,当它被设置为原型时,它实际上并没有经过函数代码,因此,“this”设置不正确Javascript 节点js原型对象';自我';var没有为回调存储正确的上下文,javascript,node.js,callback,prototypal-inheritance,Javascript,Node.js,Callback,Prototypal Inheritance,我是一名经验丰富的开发人员,但对java脚本和nodejs还不熟悉,如果这个问题的答案是“按原样”的话,我很抱歉,但是尽管我已经阅读了多个示例和stackoverflow的答案,但我没有找到一个具有正确“自”变量范围和绑定的原型类的简单完整示例(此示例)。 我两次都试了,但都出了问题。。。我将感谢你的帮助。 我试着把 var self=这个; 在我的函数声明的开头,但在运行时,当它被设置为原型时,它实际上并没有经过函数代码,因此,“this”设置不正确 /** * Module
/**
* 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上的对象。
我做错了什么
谢谢,
调用函数中的James设置
self
不会改变被调用函数中的内容。看看这个:
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
这仍然只是将对self.\u resultsPageHttpGetCallback
函数的引用传递给http.request
http.request
仍会将其作为普通函数调用,而不是方法调用,因此\u resultsPageHttpGetCallback
中的将是未定义的(严格模式)或全局对象(松散模式)
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
变量
对于您正在做的事情,函数#bind
更合适:
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
Function#bind
创建一个新函数,该函数在调用时将调用原始函数,并将this
设置为特定值
有关此
的详细信息:
- 关于堆栈溢出:
- 在我贫血的小博客上:|
以下是应用于完整代码示例的函数#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开始,其中许多功能现在可以在NodeJS中使用,因为底层V8引擎支持它们(或者,您可以使用transpiler从ES6输入生成ES5代码)
以下是使用ES2015的上述内容:
- …箭头函数,它从定义它们的上下文继承
此
,使自身
变得不必要
- …关键字
类
,它提供了一种更简洁的方法来编写构造函数和原型
- “
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 {
//...
};
最后但并非最不重要的一点:除非您真的需要\u resultsPageHttpGetCallback
和\u parsePage
作为对象的属性(它们是公共的),否则我可能会将它们设为私有函数,它们要么接受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
,因此我们通过函数调用:
/**
* Module Dependencies
*/
let cheerio = require('cheerio');
let http = require('http');
class SimplePageGetter {
constructor(pageLink) {
this._pageLink = pageLink;
}
getPage() {
http.request(this._pageLink, response => {
resultsPageHttpGetCallback.call(this, response);
}).end();
}
}
function 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', () => {
parsePage.call(this, pageBody);
});
}
function parsePage(body) {
console.log('page parsed');
}
/**
* Export
*/
module.exports = SimplePageGetter;
在调用函数中设置self
不会改变被调用函数中的内容。看看这个:
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
这仍然只是将对self.\u resultsPageHttpGetCallback
函数的引用传递给http.request
http.request
仍会将其作为普通函数调用,而不是方法调用,因此\u resultsPageHttpGetCallback
中的将是未定义的(严格模式)或全局对象(松散模式)
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
变量
对于您正在做的事情,函数#bind
更合适:
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
Function#bind
创建一个新函数,该函数在调用时将调用原始函数,并将this
设置为特定值
有关此
的详细信息:
- 关于堆栈溢出:
- 在我贫血的小博客上:|
以下是应用于完整代码示例的函数#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开始,其中许多功能现在可以在NodeJS中使用,因为底层V8引擎支持它们(或者,您可以使用transpiler从ES6输入生成ES5代码)
以下是使用ES2015的上述内容:
- …箭头函数,它从定义它们的上下文继承
此
,使自身
变得不必要
- …关键字
类
,它提供了一种更简洁的方法来编写构造函数和原型
- “
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
不像函数声明那样被提升,因此导出的标准位置通常是bott