Search code examples
node.jsmongoosemongoose-schemalibsodium

What do I misunderstand about instance methods?


So I have a schema with this method:

UserSchema.methods.comparePassword = (candidatePassword) => {
    let candidateBuf = Buffer.from(candidatePassword, 'ascii');
    if (sodium.crypto_pwhash_str_verify(this.password, candidateBuf)) {
        return true;
    };
    return false;
};

it's called thusly:

User.find({ username: req.body.username }, function(err, user) {
    isValid = user[0].comparePassword(req.body.password);
    // more stuff
}

This results in Error: argument hash must be a buffer

I am able to verify that user[0] is a valid user, obviously because it sucessfully calls the comparePassword method, and it's the libsodium function that fails.

Further test has shown that this.password is undefined. In fact, this is undefined in the comparePassword method. My understanding was that this would refer to the object from which the method is called, in this case, user[0].

So what's the correct way to refer to the object calling it's own instance method?


Solution

  • this doesn't always work the way you think it will inside an arrow function.

    fat arrow functions perform lexical scoping (essentially looking at the surrounding code and defining this based on context.)

    If you change back to regular callback function notation you will probably get the results you want:

    UserSchema.methods.comparePassword = function(candidatePassword) {
      let candidateBuf = Buffer.from(candidatePassword, 'ascii');
      if (sodium.crypto_pwhash_str_verify(this.password, candidateBuf)) {
        return true;
      };
      return false;
    };
    

    For examples of binding this: https://derickbailey.com/2015/09/28/do-es6-arrow-functions-really-solve-this-in-javascript/