无法在 node.js 对象原型函数中获取 'this'

Can't get 'this' in node.js object prototype function

我正在尝试将我的一些代码包装到节点模块中,但是出现了问题。

我的测试代码:

var Twitter_Client = require('./src/twitter-client');

var twitterClient = new Twitter_Client({
        consumer_key : '',
        consumer_secret : '',
        access_token_key : '',
        access_token_secret : ''
    });

twitterClient.tweet([{path: 'some_path', type: 'image/jpg'}],'test');

我的模块是这样的:

var Twitter = require('twitter');
var fs = require('fs');
var Promise = require("bluebird");

function Twitter_Client(opts){
    if (!(this instanceof Twitter_Client))
    return new Twitter_Client(opts);
    this._client = new Twitter(opts);
    this._tray = [];
}

Twitter_Client.prototype.makePost = (endpoint, params)=>{
    ...
};

Twitter_Client.prototype.uploadMedia = (path, type)=>{
    ...
};

Twitter_Client.prototype.tweet = (medias, status)=>{
    var that = this;
    console.log(this instanceof Twitter_Client);
    return (()=>{
        if (!Array.isArray(medias) || medias.length == 0) {
            return Promise.resolve([]);
        } else {
            return Promise.resolve(medias).map((media) => {
                return that.uploadMedia(media.path, media.type);
            });
        }
    })().then((mediaids) => {
        return new Promise((resolve,reject)=>{
            that._client.post('statuses/update', {
                status : status,
                media_ids : mediaids.join(',')
            }, function (error, tweet, response) {
                if (error) {
                    reject(error);
                }
                resolve(tweet);
            });
        });

    });
};

module.exports = Twitter_Client;

这个模块有3个函数,但是如果我post全部都太长了,所以我只展示其中一个被测试代码调用的函数。 当我 运行 上面的代码给了我:

false
Unhandled rejection TypeError: that.uploadMedia is not a function

我似乎没有从 'this' 获得正确的对象。 我读过很多类似的问题,似乎我正在以正确的方式创建对象并从对象而不是实例调用函数。 我的代码有什么问题?

问题是您将方法定义为粗箭头函数。由于粗箭头函数的工作方式,这意味着 this 值来自模块中的本地上下文,而不是来自调用该方法的对象。所以,改变这个:

Twitter_Client.prototype.tweet = (medias, status)=>{

对此:

Twitter_Client.prototype.tweet = function(medias, status){

并且,也更改所有其他方法。这是一个永远不应该使用粗箭头函数的地方,因为它们明确地破坏了对象方法的 this 值。


仅供参考,因为看起来您正在使用 Bluebird 承诺,您可以更改此设置:

        return Promise.resolve(medias).map((media) => {
            return that.uploadMedia(media.path, media.type);
        });

对此:

        return Promise.map(medias, (media) => {
            return that.uploadMedia(media.path, media.type);
        });