this 指向問(wèn)題

JavaScript 中的this指向問(wèn)題真的是被反反復(fù)復(fù)的說(shuō)起,不管是前端新人還是職場(chǎng)老鳥(niǎo),總會(huì)被這個(gè) this 搞的蒙圈,而它又是面試特別喜歡問(wèn)的問(wèn)題,所以每次面試前都要復(fù)習(xí)一下,有點(diǎn)無(wú)奈。針對(duì)這種情況,我只想說(shuō)一句“我太難了”。

難.jpg

其實(shí)要搞懂 this 指向,就要先搞清楚它的存在場(chǎng)景,主要就是三大場(chǎng)景:

  1. 普通函數(shù)中
  2. 箭頭函數(shù)中
  3. bind,call,apply

普通函數(shù)中的 this

普通函數(shù)就是非箭頭函數(shù),看 this 指向就要看它是怎么被調(diào)用的,普通函數(shù)有三種調(diào)用方式:

  1. 直接調(diào)用,如:func()
  2. 對(duì)象調(diào)用,如:obj.func()
  3. 使用 new,如:new func()

直接調(diào)用

對(duì)于直接調(diào)用的函數(shù),就不用多想了,其內(nèi)部的 this 都指向的是全局 Window對(duì)象

function func() {
  console.log(this.a) 
}
var a = 123
func() // 123

哪怕你的函數(shù)在別的函數(shù)內(nèi)部調(diào)用,只要是直接調(diào)用的,this 都指向Window,比如這樣:

function func1() {
  console.log(this.a) 
}
var a = 123

function func2() {
  var a = 456
  func1()
}
func2()  // 123

對(duì)象調(diào)用

對(duì)于對(duì)象調(diào)用,這樣的obj.func(),那 this 指向的就是前面的對(duì)象,即obj,此時(shí)只需要記住,誰(shuí)調(diào)用了函數(shù),誰(shuí)就是 this。示例:

function func() {
  console.log(this.a)
}
var a = 123

var obj = {
  a: 456,
  func: func
}

obj.func()  // 456

使用 new 調(diào)用

使用 new 調(diào)用后,this 被永遠(yuǎn)綁定在生成的實(shí)例上,不會(huì)被任何方法改變

function func() {
  console.log(this.a)
}
var a = 123

var n = new func()  // undefined,因?yàn)閷?shí)例 n 上沒(méi)有 a 屬性

箭頭函數(shù)中的 this

箭頭函數(shù)中的this,就更讓人摸不著頭腦了,其實(shí)箭頭函數(shù)里是不存在 this 的,箭頭函數(shù)中的 this 只取決包裹箭頭函數(shù)的第一個(gè)普通函數(shù)的 this,舉個(gè)例子:

function func() {
  return () => {
    return () => {
      console.log(this)
    }
  }
}
func()()() // Window

例子中,因?yàn)榘^函數(shù)的第一個(gè)普通函數(shù)是 func,所以此時(shí)的 thisWindow。

而且,箭頭函數(shù)中的 this 值,取決于它定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象,怎么理解這個(gè)呢,舉個(gè)例子:

var obj = {
  a: 123,
  func: () => {
    console.log(this.a)
  }
}
var a = 456
obj.func()

我相信很多人都會(huì)做錯(cuò)例子中的題,都會(huì)覺(jué)得打印結(jié)果是123,而正確答案應(yīng)該是456。因?yàn)?strong>箭頭函數(shù)中的this值取決于定義時(shí)的對(duì)象,而不是調(diào)用時(shí)的對(duì)象,這跟普通函數(shù)相反的。func定義在對(duì)象obj中,此對(duì)象不具備作用域,所以this指向全局Window

bind,call,apply

這三個(gè)也不用多說(shuō),this是第一個(gè)參數(shù)。這里重點(diǎn)說(shuō)一下bind,如果對(duì)一個(gè)函數(shù)進(jìn)行多次 bind,那么最終this指向誰(shuí)?例子:

var a = { name: 'a' }
var b = { name: 'b' }
function func() {
  console.log(this)
}
func.bind(a).bind(b)()

例子中的輸出結(jié)果是a而不是b,記住不管我們給函數(shù) bind 幾次,func 中的 this 永遠(yuǎn)由第一次 bind 決定。而applycall因?yàn)榻壎ǖ耐瑫r(shí)就執(zhí)行了函數(shù),所以不支持這種鏈?zhǔn)浇壎ā?/p>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容