[英]node js prototype object 'self' var does not store correct context for callback
我是一位經驗豐富的開發人員,但是對Java腳本和Node.js還是陌生的,如果這個問題已按原樣回答,我深表歉意,但是即使我遍歷了多個示例和stackoverflow答案,也沒有找到原型類的簡單完整示例正確的'self'變量作用域和綁定(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上的對象。 請問我做錯了什么?
謝謝 ,
詹姆士
設置self
調用函數中沒有做任何事情去改變什么this
被稱為將是功能。 所以看這個:
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
那仍然只是將對self._resultsPageHttpGetCallback
函數的引用傳遞給http.request
。 http.request
仍將其僅作為普通函數而不是方法來調用,因此_resultsPageHttpGetCallback
this
_resultsPageHttpGetCallback
將是未定義的(嚴格模式)或全局對象(寬松的模式)。
self
模式對於在同一作用域(或嵌套作用域)中創建的函數很有用,例如:
function someMethod() {
var self = this;
http.request(self._pageLink, function(err, data) {
// Use `self` here to access object info
}).end();
}
之所以http.request
是因為我要傳遞給http.request
的匿名函數關閉 (具有對它的創建上下文)的引用,並且該上下文具有self
變量,因此該函數可以訪問self
變量。
對於您正在做的事情, Function#bind
會更合適:
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
Function#bind
創建一個新函數,該新函數在被調用時將調用此函數並將this
設置為特定值。
有關this
更多信息:
this
關鍵字如何工作? 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)的新功能,因為底層V8引擎支持它們,所以您現在可以從v4開始在NodeJS中使用其中的許多功能(或者,您可以使用轉譯器從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
成為對象的屬性(它們是公共的),否則我可能會將它們設為私有函數,這些函數要么接受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
對其進行Function#call
:
/**
* 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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.