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ō)一句“我太難了”。

其實(shí)要搞懂 this 指向,就要先搞清楚它的存在場(chǎng)景,主要就是三大場(chǎng)景:
- 普通函數(shù)中
- 箭頭函數(shù)中
- bind,call,apply
普通函數(shù)中的 this
普通函數(shù)就是非箭頭函數(shù),看 this 指向就要看它是怎么被調(diào)用的,普通函數(shù)有三種調(diào)用方式:
- 直接調(diào)用,如:
func() - 對(duì)象調(diào)用,如:
obj.func() - 使用 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í)的 this 是 Window。
而且,箭頭函數(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 決定。而apply和 call因?yàn)榻壎ǖ耐瑫r(shí)就執(zhí)行了函數(shù),所以不支持這種鏈?zhǔn)浇壎ā?/p>