关于Mongoose中箭头函数与词法this的疑问求解
Great question—this is a super common point of confusion when mixing ES6 arrow functions with libraries like Mongoose that rely heavily on this binding. Let's break it down clearly:
First: How Arrow Functions Handle this
You're right that arrow functions use lexical scoping for this—meaning they don't have their own this value. Instead, they inherit the this from the surrounding code where the arrow function is defined, not where it's called. This is a key difference from regular functions, whose this is determined by how they're invoked.
Now: How Mongoose Schema Methods Work
When you add a method to a Mongoose Schema (using schema.methods.[methodName]), Mongoose is designed to explicitly bind this to the document instance when that method is called. For example, if you create a User document and call user.greet(), Mongoose makes sure this inside greet points to that specific user object—so you can access properties like this.name or methods like this.save().
The Conflict
Here's why arrow functions break this:
- When you define an arrow function as a Schema method, it captures the
thisfrom the context where you wrote the arrow function. In most cases, this is the global context (Node.js'sglobalobject) or the module's top-level context (not the Mongoose document instance). - Arrow functions can't have their
thisre-bound later—even if Mongoose tries to setthisto the document instance, the arrow function will ignore it and keep using the lexicalthisit captured at definition time.
Example to Illustrate
Working regular function:
const userSchema = new mongoose.Schema({ name: String }); userSchema.methods.sayHello = function() { console.log(`Hi, I'm ${this.name}`); // `this` is bound to the document instance by Mongoose }; const User = mongoose.model('User', userSchema); const alice = new User({ name: 'Alice' }); alice.sayHello(); // Output: Hi, I'm Alice
Broken arrow function:
userSchema.methods.sayHello = () => { console.log(`Hi, I'm ${this.name}`); // `this` is the lexical context (e.g., global object), not the document }; alice.sayHello(); // Output: Hi, I'm undefined (or throws an error)
Key Takeaway
Mongoose relies on regular functions to enable dynamic this binding to document instances. Arrow functions, with their fixed lexical this, can't participate in this mechanism—so you'll always want to use regular functions for Schema methods, statics, and middleware.
内容的提问来源于stack exchange,提问作者CoderXYZ

