在回调中对此有困惑

时间:2017-11-25 12:43:15

标签: javascript node.js mongoose

我对回调中的这个值感到很困惑,我知道这个值总是取自它的调用位置,但是在下面的代码中,我无法弄清楚&#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的上下文中调用的。

嗯,我知道这是一个奇怪的问题。

3 个答案:

答案 0 :(得分:3)

JavaScript函数中的

this指的是执行上下文,并且在正常情况下(不是ES6特定的“箭头”函数)通常等于上下文,函数被调用。但是“this”可以通过例如使用Function对象的bindcallapply方法为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.hooksthis.queue(...)的性质: - )

答案 2 :(得分:1)

this绑定到函数的调用站点。它也可以绑定到您指定的位置以使用callapplybind等函数方法绑定到它。



function foo () {
  var a = 5;
  console.log(this.a);
}

var a = 2;

foo(); // 2




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