无法在同一个类JS的另一个方法中调用方法

我正在尝试在同一个类的方法连接中调用方法testing。 但我所得到的是“未捕获types错误:不能读取未定义的属性'testing'。 如何访问sftpcallback中的任何variables? 为什么这样?

这是我的代码:

const SSH2 = require('ssh2').Client; class SshClient { constructor(host, username, password) { this.host = host; this.username = username; this.password = password; this.port = 22; this.client = null; } test(testvar) { console.log(testvar); } connect() { this.client = new SSH2(); let client = this.client; let username = this.username; this.client.connect({ host: this.host, port: this.port, username: this.username, password: this.password }); this.client.on('ready', function() { console.log('Client :: ready', client); client.sftp(function(err, sftp) { if (err) throw err; sftp.readdir('/home/' + username, function(err, list) { if (err) throw err; console.dir(list); this.test('hey'); client.end(); }); }); }); } } let ssh = new SshClient('host', 'username', 'password'); ssh.connect(); 

当使用function() {你正在进入一个新的上下文,而不是你的类上下文。 使用es6 arrow functions ,您可以轻松地将您的类上下文分享到内部函数中。


  this.client.on('ready', () => { client.sftp((err, sftp) => { if (err) throw err; sftp.readdir('/home/' + username, (err, list) => { if (err) throw err; this.test('hey'); client.end(); }); }); }); 

这里有一篇很好的关于es6 arrow functions是如何工作的文章,以及它们如何影响this

当您将该函数用作callback(将其作为parameter passing给另一个函数)时,callback中的thisvariables不会指向您的对象。

如果分别定义callback,则会更清晰:

 class SshClient { constructor(host, username, password) { //... } test(testvar) { console.log(testvar); } connect() { this.client = new SSH2(); // ... this.client.on('ready', onReadyCallback); } } function onReadyCallback() { console.log('Client :: ready', client); client.sftp(sftpCallback); } function sftpCallback(err, sftp) { if (err) throw err; sftp.readdir('/home/' + username, readdirCallback); } function readdirCallback(err, list) { if (err) throw err; console.dir(list); this.test('hey'); // It is clear that `this` here doesn't refer // to the SshClient object client.end(); }); 

正如你所看到的, readdirCallback中的这个readdirCallback不正确,这个函数不是SshClient类的一部分,也不能指向SshClient对象。

最简单的解决scheme是在代码中对clientusernamevariables做同样的事情 – 将其保存到其他variables中:

  connect() { this.client = new SSH2(); let self = this; // ... this.client.on('ready', function() { // we can use "self" variable here, // as it's avaialbe from the outer scope self.client; // we can refer to client and username self.username; self.test(); // and we can call object methods }); } 

另外一个select是保持callback分开,并捕捉你的对象进一步closures:

 class SshClient { connect() { this.client = new SSH2(); // ... this.client.on('ready', getOnReadyCallback(this)); } } function getOnReadyCallback(sshClient) { function onReadyCallback() { console.log('Client :: ready', sshClient.client); sshClient.client.sftp(getSftpCallback(sshClient)); } } 

在其他答案中提到的箭头函数可能是最好的解决scheme,因为您不需要任何解决方法,但是您必须清楚地了解问题是什么以及为什么箭头函数可以解决问题:

箭头函数expression式的语法比函数expression式更短,并且没有自己的this,arguments,super或new.target。 这些函数expression式最适合于非方法函数,并且不能用作构造函数。

箭头函数没有自己的this – 所以如果你使用箭头函数作为callback,原始对象的this保持可用。