2017-11-25 281 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被綁定到詞法作用域。