Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 节点js原型对象';自我';var没有为回调存储正确的上下文_Javascript_Node.js_Callback_Prototypal Inheritance - Fatal编程技术网

Javascript 节点js原型对象';自我';var没有为回调存储正确的上下文

Javascript 节点js原型对象';自我';var没有为回调存储正确的上下文,javascript,node.js,callback,prototypal-inheritance,Javascript,Node.js,Callback,Prototypal Inheritance,我是一名经验丰富的开发人员,但对java脚本和nodejs还不熟悉,如果这个问题的答案是“按原样”的话,我很抱歉,但是尽管我已经阅读了多个示例和stackoverflow的答案,但我没有找到一个具有正确“自”变量范围和绑定的原型类的简单完整示例(此示例)。 我两次都试了,但都出了问题。。。我将感谢你的帮助。 我试着把 var self=这个; 在我的函数声明的开头,但在运行时,当它被设置为原型时,它实际上并没有经过函数代码,因此,“this”设置不正确 /** * Module

我是一名经验丰富的开发人员,但对java脚本和nodejs还不熟悉,如果这个问题的答案是“按原样”的话,我很抱歉,但是尽管我已经阅读了多个示例和stackoverflow的答案,但我没有找到一个具有正确“自”变量范围和绑定的原型类的简单完整示例(此示例)。 我两次都试了,但都出了问题。。。我将感谢你的帮助。 我试着把 var self=这个; 在我的函数声明的开头,但在运行时,当它被设置为原型时,它实际上并没有经过函数代码,因此,“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上的对象。 我做错了什么

谢谢,


调用函数中的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