我对回调中的这个值感到很困惑,我知道这个值总是取自它的调用位置,但是在下面的代码中,我无法弄清楚&#39发生了。
userSchema.pre("save", function(next) {
let user = this;
bcrypt.hash(user.password, 10, function(err, hash) {
if (err) {
next(err)
} else {
user.password = hash;
next();
}
})
});
我正在用mongoose观看节点js的教程,所以教练说: 在此回调函数的上下文中,单词 this 指的是对象,
let userSchema = new mongoose.Schema({
password: {
type: String,
required: true
}
});
这里user = this
不应该引用节点全局对象而不是那个对象吗?
所以我真的很困惑,例如,如果我尝试在简单的JavaScript中模仿这个代码行为。
function UserSchema() {
this.pre = function(cb) {
return cb();
}
}
function Bycrypt() {
this.hash = function(cb) {
return cb();
}
}
userSchema.pre(function() {
var user = this;
bycrypt.hash(function() {
console.log(user)
})
});
这会将用户记录为 Window 对象,因为回调函数是在Window的上下文中调用的。
嗯,我知道这是一个奇怪的问题。
答案 0 :(得分:3)
this
指的是执行上下文,并且在正常情况下(不是ES6特定的“箭头”函数)通常等于上下文,函数被调用。但是“this”可以通过例如使用Function对象的bind,call或apply方法为this
传递不同的值。
您可以在MDN上阅读this article以获取详细信息。
答案 1 :(得分:1)
这根本不是一个奇怪的问题,this
关键字通常是混淆的原因,因为它具有隐含性:-)无论如何,我不知道pre
函数是如何实现的,但我们可以轻易想象出类似的东西:
schema = {
whoami: "a schema"
};
schema.pre = function (cb) {
return cb.call(this);
}
schema.pre(function () {
console.log(this.whoami);
});
call
函数是一个JavaScript内置函数,允许更改函数的默认主题(window
)。浏览源代码我发现似乎是pre
函数的东西(不是100%肯定):https://github.com/Automattic/mongoose/blob/master/lib/schema.js#L1138。正如您所看到的,他们使用的apply
内置函数与call
具有相同的效果。让我们看看它们有何不同:
function f(a, b) {
console.log("I am", this.whoami);
console.log("Arguments :", "[" + a + ", " + b + "]");
}
f.call({ whoami: "A" }, "b", "c");
f.apply({ whoami: "X" }, ["y", "z"]);
我相信这可以成为调查的良好起点。我让您深入了解源代码,了解this.s.hooks
和this.queue(...)
的性质: - )
答案 2 :(得分:1)
this
绑定到函数的调用站点。它也可以绑定到您指定的位置以使用call
,apply
和bind
等函数方法绑定到它。
function foo () {
var a = 5;
console.log(this.a);
}
var a = 2;
foo(); // 2

使用ES6箭头功能,this
绑定到词法范围。