无法在同一 class JS 的另一个方法中调用方法
Not able to call method within another method of the same class JS
我正在尝试在同一个 class 的连接方法中调用方法测试。但我得到的只是 "Uncaught Type Error: Cannot read property 'test' of undefined"。
如何访问 sftp 回调中的任何变量?
为什么会这样?
这是我的代码:
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() {
时,您将进入一个新的环境,这不是您的 class 环境。使用 es6 arrow functions
,您可以轻松地将 class 上下文共享到内部函数中。
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();
});
});
});
Here 是一篇关于 es6 arrow functions
如何运作以及它们如何影响 this
的好文章。
当您将函数用作回调(将其作为参数传递给另一个函数)时,回调中的 this
变量未指向您的对象。
如果单独定义回调,会更清楚:
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
中的 this
看起来不再正确,该函数不属于 SshClient
class 和 this
不能指向 SshClient
对象。
最简单的解决方案是对代码中的 client
和 username
变量执行相同的操作 - 将 this
保存到附加变量中:
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
});
}
另一种选择是将回调分开并将您的对象捕获到额外的闭包中:
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));
}
}
另一个答案中提到的arrow functions可能是最好的解决方案,因为您不需要任何变通方法,但是您必须清楚地了解问题所在以及箭头函数解决问题的原因:
An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.
箭头函数没有自己的 this
- 因此如果您使用箭头函数作为回调,原始对象的 this
仍然可用。
我正在尝试在同一个 class 的连接方法中调用方法测试。但我得到的只是 "Uncaught Type Error: Cannot read property 'test' of undefined"。 如何访问 sftp 回调中的任何变量? 为什么会这样?
这是我的代码:
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() {
时,您将进入一个新的环境,这不是您的 class 环境。使用 es6 arrow functions
,您可以轻松地将 class 上下文共享到内部函数中。
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();
});
});
});
Here 是一篇关于 es6 arrow functions
如何运作以及它们如何影响 this
的好文章。
当您将函数用作回调(将其作为参数传递给另一个函数)时,回调中的 this
变量未指向您的对象。
如果单独定义回调,会更清楚:
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
中的 this
看起来不再正确,该函数不属于 SshClient
class 和 this
不能指向 SshClient
对象。
最简单的解决方案是对代码中的 client
和 username
变量执行相同的操作 - 将 this
保存到附加变量中:
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
});
}
另一种选择是将回调分开并将您的对象捕获到额外的闭包中:
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));
}
}
另一个答案中提到的arrow functions可能是最好的解决方案,因为您不需要任何变通方法,但是您必须清楚地了解问题所在以及箭头函数解决问题的原因:
An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.
箭头函数没有自己的 this
- 因此如果您使用箭头函数作为回调,原始对象的 this
仍然可用。