Ondrej Tokar Ondrej Tokar - 4 months ago 10
Node.js Question

Do I have to use "this." to work with "object" attributes in NodeJs?

I am switching from Java to NodeJs so some things are still blurry to me.

I am trying to work with scripts as I would do with classes in Java. I've learned this is the way to do it:

var client = require('scp2');
var host, username, password;

var SftpHandler = function (host, username, password) {
this.host = host;
this.username = username;
this.password = password;
};



SftpHandler.prototype.downloadFile = function (path, callback) {
console.log(this.host,username,password,path);
};

module.exports = SftpHandler;


The problem is when I call it from another script like this:

var sftpHandler = new SftpHandler(credentials.sftpHost, credentials.sftpUsername, credentials.sftpPassword);
sftpHandler.downloadFile(credentials.sftpPathToImportFiles+configFile.importFileName, callback);


I am having
162.*.*.* undefined undefined undefined ...
in the console log.

I've realized it is due to I am lacking
this.
in the object attributes I am referring to. But why is
this.
needed? Is that the right way to do it?

Answer

It's a little tricky to map concepts between Java and JavaScript sometimes.

The short answer is, yes, if you are going to try and make something that's like a class instance in Java in JavaScript, then you need to call 'this' every time.

The reason is that this in JS is actually a special, locally scoped variable inside a function that refers to the calling scope. It's not always the actual class instance, believe it or not, so you need to read up on it more thoroughly.

Many folks choose not to try, as there are a number of places that following Java idioms will either get you into trouble, or else just make things more difficult / complex / hard to maintain.

But in any case, as an example of how this can change, if your downloadFile method needed to provide a nested function, for example you wanted to handle a callback with an anonymous function:

SftpHandler.prototype.downloadFile = function (path, callback) {
    console.log(this.host); // this here refers to your object instance
    fileManager.getFile(path, function(e, file){
       console.log(this.host); // 'this' here refers to the anonymous function, not your object
    })
};

Hope that helps.

** Edit for how to get to this inside the callback **

There's a couple ways to maintain the reference. It's very common to just set another variable in scope to the original this, like so:

SftpHandler.prototype.downloadFile = function (path, callback) {
    console.log(this.host); // this here refers to your object instance
    var self = this;

    fileManager.getFile(path, function(e, file){
       console.log(this.host); // 'this' here refers to the anonymous function, not your object
       console.log(self.host); // 'self' there refers to the enclosing method's 'this'
    })
};

Others prefer to be more explicit with the use of Function#bind:

SftpHandler.prototype.downloadFile = function (path, callback) {
    console.log(this.host); // this here refers to your object instance
    fileManager.getFile(path, function(e, file){
       console.log(this.host); // 'this' here refers to the your object thanks to bind()
    }.bind(this));
};