在另一个函数中使用此实例访问用户密码变量

Accessing user password variable using this instance inside another function

我正在尝试对用户进行身份验证,但我在邮递员中收到此错误

{
"error": "data and hash arguments required"
}

我的用户模型是这样的:

const mongoose = require('mongoose')
const bcrypt = require('bcrypt')
const SALT_WORK_FACTOR = 10
const Schema = mongoose.Schema

const UserSchema = new Schema({
  username: { type: String, required: true, index: { unique: true } },
  password: { type: String, required: true }
})
UserSchema.pre('save', function (next) {
  let user = this

  // only hash the password if it has been modified(or is new)
  if (!user.isModified('password')) return next()

  // generate a salt
  bcrypt.genSalt(SALT_WORK_FACTOR, (err, salt) => {
    if (err) return next()

    // hash the password along with our new salt
    bcrypt.hash(user.password, salt, (err, hash) => {
      if (err) return next(err)
      // override the cleartext password with the hashed one
      user.password = hash
      next()
    })
  })
})
UserSchema.methods.comparePassword = (candidatePassword, callback) => {
  console.log('Password', this.password)// undefined
  bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
    callback(err, isMatch)
  })
}
module.exports = mongoose.model('userData', UserSchema, 'userData')

我发现传递给 bcrypt 比较函数的 this.password 解析为 undefined 。如何访问上面 UserSchema 实例中定义的密码变量?

显然在 javascript 中,this 在对象调用函数之前不会被赋值,从而将 this 绑定到方法的所有者(调用对象)。 在上面的问题中,我使用了 es6 箭头函数,其 this 绑定到直接周围的范围(词法范围),因此无法找到定义的 属性 password UserSchema 并且未绑定到箭头函数中 this 的范围。
示例:

var Utils = {
  printName: function(somename) {
    console.log(somename)
  }
}

var person = {
  firstName: "Gregory",
  lastNames: ["Baltimore", "Barry", "Derrick", "Evanson"],
  fullName: function() {
    this.lastNames.forEach(lastname => {
     //this points to person object
      Utils.printName(this.firstName + " " + lastname) //output Gregory Baltimore Gregory Barry Gregory Derrick Gregory Evanson
    })
  }
}

person.fullName()

注意this es6 箭头函数内部指向person 对象,这是它的静态范围(词法)。让我们从es5 的角度看一下同一段代码

 var Utils = {
      printName: function(somename) {
        console.log(somename)
      }
    }

    var person = {
      firstName: "Gregory",
      lastNames: ["Baltimore", "Barry", "Derrick", "Evanson"],
      fullName: function() {
        this.lastNames.forEach(function(lastname) {
    //this points to global object
          Utils.printName(this.firstName + " " + lastname)  //output undefined Baltimore undefined Barry undefined Derrick undefined Evanson 
        })
      }
    }

    person.fullName()

你会注意到 firstname 被打印为 undefined.This 是因为在 es5 中 this 超出了范围,因此默认情况下(Javascript 怪癖)绑定到全局 object.In 浏览器这个全局对象是 Nodejs 中的 window 全局对象是 Nodejs 环境(运行时),如果用户没有定义的话。(例如在模块导出中) 为了解决我的问题,我默认使用 es5 函数,因为密码 属性 绑定到我定义为 UserSchema.Thus 密码 属性 的全局对象已正确解析

 UserSchema.methods.comparePassword = function (candidatePassword, callback) {
  //Now this is bound to the UserSchema object
  bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
    callback(err, isMatch)
  })
}

可在此处找到更多信息 Understand JavaScript’s “this” With Clarity, and Master It

这里也是 Arrow functions and the ‘this’ keyword