淺析JS中的this

JS 中的this到底是什么

首先說結論:

fn.call (context,argument[]) ,this 就是你 call 一個函數時,傳入的 context。

那大家肯定有疑問,函數調用形式多鐘,如果不是這種調用形式呢?那又如何確定this呢?
接下來我們先從函數調用形式說起

函數調用形式

JS(ES5)里面有三種函數調用形式:

fn(p1, p2) 
obj.child.method(p1, p2)
fn.call(context, p1, p2) //標準調用形式

其中,第三種調用形式,才是正常調用形式函數調用標準形式

fn.call(context, p1, p2)

其他兩種都是語法糖,可以等價地變為 call 形式:

fn(p1, p2) 等價于
fn.call(undefined, p1, p2)

obj.child.method(p1, p2) 等價于
obj.child.method.call(obj.child, p1, p2)

所以,我們知道不論哪種情況的函數調用,都可以轉換為標準形式:

fn.call(context, p1, p2)

如此,只要是函數調用,你就可以輕松的知道this的傳入形式。如果你的函數調用形式不是 call 形式,請按照「轉換代碼」將其轉換為 call 形式。

this 傳入的是什么?

在了解this 就是 call 一個函數時,傳入的 context后,我們還需要了解他傳入的是什么

首先我們構造一個監聽函數

$div.on('click',function(){
  conlose.log('click')
  conlose.log('this')
})
click
<div></div>

在這個監聽函數中,我們發現,打印出this就是我們監聽的元素
那么this是否就是這個監聽元素嗎?實際不是這樣的

接下來我們繼續構造一個事件委托

 $div.on('click','button',function(){
  conlose.log('click')
  conlose.log('this')
})
click
<button></button>

在這個事件委托中,打印出的this是我們點擊的元素(button),并不是我們監聽的元素

那么現在結論出來了,this ===e.currentTaget ?

$div.on('click','button',function(e){
  conlose.log('click')
  if (this === e.currentTaget){
    conlose.log('true')
  }
})
click
true

實際證明,的確如此。

通常性看來,this 在JS中是多余的,它只是為了看起來像Java而設定的

this的使用方式

在一個對象里, 可以用this表示一個對象

通常時候,其實this是多余的,我們可以直接用對象名,而不使用this。

但是,某些時候,我們并不知道對象名,這時候就不得不用this來替代了。

let module = {
  element: null,
  init: function(){
    let $div = this.element  //this.element = module.element
                             //在這里,對象名module可以用this替代
    $div.on('click','button',this.onClickButton)
    $div.on('click',function(){
      conlose.log('click')
    })
  },
  onClickButton: function(e){
    console.log('button is click')
  }
}
module.init($div) // 等同于 module.init.call(module,$div)

但是 this在一個對象中,是可以改變的

let module = {
  element: null,
  init: function(){
    let $div = this.element  
    $div.on('click','button',this.onClickButton)  //這里的this === module
  },
  onClickButton: function(e){
    console.log('button is click')
    console.log('this')  //由于觸發了click監聽事件,這里的this已經變成了監聽事件的點擊元素button
  }
}
module.init($div) // 等同于 module.init.call(module,$div)

上例中,由于監聽事件的this的值是指向觸發事件的元素。所以this已經改變

可以看出,this在特定場景下,是會根據API的源代碼定義所改變。

那么如果我們想指定監聽事件傳入的this是我們想要的this,怎么辦?

$div.on('click','button',function(){
  module.onClickButton.call(module,e)  //這里我們強制指定了傳入this值為module
})  

$div.on('click','button',this.onClickButton.bind(this))

我們還可以用bind 來實現

$div.on('click','button',this.onClickButton.bind(this))

總結

  1. this 就是你 call 一個函數時,傳入的 context
  2. 如果函數調用形式不是 call 形式,請將其轉換為 call 形式
  3. 在一個對象里, 可以用this表示一個對象
  4. 在監聽事件里,this的值是指向觸發事件的元素
  5. 任何函數都可以強制指定傳入的this,也可以使用bind來改變默認傳入this
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,827評論 2 17
  • 1.JQuery 基礎 改變web開發人員創造搞交互性界面的方式。設計者無需花費時間糾纏JS復雜的高級特性。 1....
    LaBaby_閱讀 1,200評論 0 1
  • 1.JQuery 基礎 改變web開發人員創造搞交互性界面的方式。設計者無需花費時間糾纏JS復雜的高級特性。 1....
    LaBaby_閱讀 1,367評論 0 2
  • 【我的閱讀】《直心真實,老虎為徒》 牛頭山慧忠禪師被稱為山主,可能是因為他能與萬物溝通的緣故。 當時政府劃給寺院二...
    一畝岐江閱讀 452評論 1 3
  • 月落烏啼霜滿天,江楓漁火對愁眠 姑蘇城外寒山寺,夜半鐘聲到客船 冬日的陽光是恩賜,我被這恩賜眷顧,在這暖暖陽光下,...
    emilychan閱讀 741評論 0 0