你不知道的This和Class

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

一、何謂this

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