javascript this 的含義

 

var obj = {
  foo: function(){
    console.log(this)
  }
}

var bar = obj.foo
obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window

請解釋最後兩行函數的值爲什麼不一樣。

 

函數調用

首先需要從函數的調用開始講起。

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

 

 

func(p1, p2) 
obj.child.method(p1, p2)
func.call(context, p1, p2) // 先不講 apply

 

 

一般,初學者都知道前兩種形式,而且認爲前兩種形式「優於」第三種形式。

從看到這篇文章起,你一定要記住,第三種調用形式,纔是正常調用形式:

func.call(context, p1, p2)

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

func(p1, p2) 等價於
func.call(undefined, p1, p2)

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

請記下來。(我們稱此代碼爲「轉換代碼」,方便下文引用)

至此我們的函數調用只有一種形式:

func.call(context, p1, p2)

這樣,this 就好解釋了

this,就是上面代碼中的 context。就這麼簡單。

this 是你 call 一個函數時傳的 context,由於你從來不用 call 形式的函數調用,所以你一直不知道。

先看 func(p1, p2) 中的 this 如何確定:

當你寫下面代碼時

function func(){
  console.log(this)
}

func()

用「轉換代碼」把它轉化一下,得到

function func(){
  console.log(this)
}

func.call(undefined) // 可以簡寫爲 func.call()

按理說打印出來的 this 應該就是 undefined 了吧,但是瀏覽器裏有一條規則:

如果你傳的 context 是 null 或 undefined,那麼 window 對象就是默認的 context(嚴格模式下默認 context 是 undefined)

因此上面的打印結果是 window。

如果你希望這裏的 this 不是 window,很簡單:

func.call(obj) // 那麼裏面的 this 就是 obj 對象了

 

再看 obj.child.method(p1, p2) 的 this 如何確定

var obj = {
  foo: function(){
    console.log(this)
  }
}

obj.foo() 

按照「轉換代碼」,我們將 obj.foo() 轉換爲

obj.foo.call(obj)

好了,this 就是 obj。搞定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章