2017-11-25 219 views
2

我真的很困惑这个回调的价值,以及我知道这个值总是取自它被调用的地方,但在下面的代码中,我无法弄清楚发生了什么。关于回调的困惑

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(); 
     } 
    }) 
}); 

我正在看与猫鼬节点JS的教程,因此教练说: 在该回调函数的上下文中,词语指对象,这是

let userSchema = new mongoose.Schema({ 
    password: { 
     type: String, 
     required: true 
    } 
}); 

这里不应该指代Node Global Object而不是那个对象吗?

所以我真的很困惑这是怎么发生的,例如,如果我试图在简单的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) 
    }) 
}); 

因为回调函数在窗口的上下文称这将记录用户为窗口对象。

好吧,我知道这是一个奇怪的问题要问。

+0

在你的代码演示中使用下面的答案:https://jsfiddle.net/e9p3677c/ –

+0

答案更新:https://stackoverflow.com/a/47486224/1636522 :-) – leaf

回答

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(...) :-)

+0

现在事情开始变得有些感觉,但是你能向我解释,如果'userSchema.pre'的上下文被设置为'userSchema'。那么我们不能直接将'this.password'传递给回调函数中的'bcrypt.hash',而不必将此引用存储在用户变量中,然后将其传递给'bcrypt.hash'。 –

+0

@OsamaXäwãñzThe问题在于'this'可能引用回调中的不同对象: - | – leaf

+0

@OsamaXäwãñz我不确定要理解你的问题,但: - | – leaf

3

在JavaScript函数this是指执行上下文和正常(不ES6特定的“箭头”的功能)的情况下,通常等于上下文中,函数被调用。但是,“this”可以通过例如使用bind,callapply函数对象的方法为this传递不同的值。

有关详细信息,您可以阅读MDN上的this article

1

this绑定到函数的调用位置。也可以使用函数方法(如call,applybind)将其绑定到指定的位置。

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

 
var a = 2; 
 

 
foo(); // 2

随着ES6箭头功能,this被绑定到词法作用域。