你不知道的This和Class

  • Oh no....我的This又丟失了???
  • 為什么我用Class'實(shí)例化'出來的對象會相互影響??? ####這些問題都是因?yàn)镴S的運(yùn)行機(jī)制造成的。在JS中所有的一切都是對象,而this是對象的一個屬性。在對象被調(diào)用時,this動態(tài)的根據(jù)上下文環(huán)境進(jìn)行綁定,因此this和詞法作用域沒有關(guān)系。

一、何謂this

  1. this是函數(shù)執(zhí)行上下文對象的一個屬性,存在于運(yùn)行時,而不是定義時,所以它和詞法作用域沒有必然的關(guān)系。
  2. 要使用this,首先需要考慮的是函數(shù)的調(diào)用環(huán)境而不是編寫定義環(huán)境。它不指向函數(shù)本身,也不指向詞法作用域。它由函數(shù)調(diào)用時發(fā)生在上下文環(huán)境的綁定而決定。
  3. 使用this要找函數(shù)的調(diào)用位置,而不是函數(shù)的聲明位置。調(diào)用棧記錄了函數(shù)的調(diào)用位置和順序。通過調(diào)試工具可以查看調(diào)用棧,找出函數(shù)的調(diào)用位置。調(diào)用時使用了誰的上下文,this就指向誰。特別要注意的是回調(diào)函數(shù)傳遞的是引用,所以會丟失this。真正執(zhí)行回調(diào)函數(shù)的位置決定了this的指向。
  4. bind把用來硬綁定函數(shù)執(zhí)行的上下文,用于硬綁定this。(在React組件構(gòu)造函數(shù)中顯示的綁定This,防止丟失上下文環(huán)境)。除此之外,賦值表達(dá)式會傳遞函數(shù)的引用,它的調(diào)用位置會變成函數(shù)聲明的位置。
  5. JS中Class對象的構(gòu)造函數(shù)不是其它面向?qū)ο笳Z言的構(gòu)造函數(shù),它是對已有函數(shù)的構(gòu)造調(diào)用,本質(zhì)上也是This的綁定。new關(guān)鍵字看上去像實(shí)例化對象,其實(shí)只是根據(jù)已有函數(shù)生成新的函數(shù)對象,并通過new關(guān)鍵字將this綁定到新創(chuàng)建的對象的調(diào)用上下文環(huán)境中。比如,var test =new foo(),用 new 來 調(diào)用 foo(..) 時,我們會構(gòu)造一個新對象并把它綁定到foo(..) 調(diào)用中的 this 上。
  6. 箭頭函數(shù)本身沒有this,它在執(zhí)行時會捕獲調(diào)用所在詞法作用域父函數(shù)的this。捕獲綁定之后無法再次被修改。()=>的this是和詞法作用域有關(guān)系的。而function定義的函數(shù)是和詞法作用域沒有關(guān)系的,只和調(diào)用環(huán)境有關(guān)系。http://stackoverflow.com/questions/35813344/do-es6-arrow-functions-still-close-over-this-even-if-they-dont-use-it
  7. this和JS中的Class可以關(guān)聯(lián)使用,通過this的重新綁定可以實(shí)現(xiàn)混入 '父類'屬相和方法的功能,也就實(shí)現(xiàn)了隱士的類似Class的偽多態(tài)。
根據(jù)下面這四條規(guī)則來判斷this的綁定對象。
  1. 由 new 調(diào)用? 綁 定 到 新 創(chuàng)建 的 對象。
  2. 由 call 或者 apply( 或者 bind) 調(diào)用? 綁 定 到 指定 的 對象。
  3. 由上下文對象調(diào)用? 綁定到那個下文對象。
  4. 默認(rèn): 在嚴(yán)格模式下綁定到undefined,否則 綁 定 到 全局 對象。
  5. 網(wǎng)友評論