"this"对象在pre('save')中为空

Józ*_*akó 7 mongoose

正如我在标题中描述的那样,当我想要保存一个新的mongoose 文档时,该pre('save')方法会触发,但其中的this元素是一个emtpty对象.

测试片段:

var schema = new mongoose.Schema({
    password:String
})

schema.pre('save',(next)=>{
    console.log(this)
    next()
})

var model = mongoose.model('Test',schema)

var test = new model({
    password:'testpass'
})

test.save()
Run Code Online (Sandbox Code Playgroud)

我无法看到这个基本代码的问题.

我使用的是Mongoose v4.5.9.

unR*_*unR 46

无论出于何种原因,您的函数都不能使用es6箭头语法

schema.pre('save', function(next) {
    console.log(this)
    next()
})
Run Code Online (Sandbox Code Playgroud)

将工作.我目前不知道为什么.

  • 谢谢!的确,我应该考虑一下.Arrow函数"保持"上下文(`this`),这意味着在这种情况下,`this`不是刚刚保存的对象,而是Schema实例. (4认同)
  • 谢谢!我浪费了几个小时! (3认同)
  • 那是因为**箭头函数没有自己的`this`**,所以他们从外部范围(在这种情况下可能是全局对象)获得`this`,而**不是**Mongoose试图传递的内容(文档)。 (2认同)

小智 6

用户“ unR”的答案是正确的。this在预保存功能上使用箭头功能时,无法使用。您还将在所有其他类型的猫鼬模式函数中找到此功能。我已经扩展了这个答案,以帮助弄清为什么会这样。

这打破了:

schema.pre('save', (next) => { // arrow function
  console.log(this);
  next();
});
Run Code Online (Sandbox Code Playgroud)

这有效:

schema.pre('save', function preSave(next) { // regular function
  console.log(this);
  next();
});
Run Code Online (Sandbox Code Playgroud)

原因:

出现问题是因为箭头功能与常规功能不同地对待“ 范围 ”。箭头函数不会将范围保留在函数内,而是从外部或周围的函数强制继承范围(这意味着它将覆盖)之类的函数exampleMethod.bind(this)。在上述情况下;没有外部函数,因此该this值等于undefined

但是,当您使用常规函数声明时,可以使用该.bind()方法用猫鼬覆盖范围。这样,它们将功能绑定到架构对象,使您可以访问功能中的架构属性和功能。

这是有关箭头功能及其工作方式的有用资源:https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions