你能搞懂JavaScript的this指向問題嗎?以下這篇文章帶大家聊聊這令人煩惱的this指向問題,希望對大家有幫助!
在我們看見的各種介紹如何判斷this的指向方法中,"this的最終指向的是那個調用它的物件" 這句話被視作核心,但是面對多種多樣的情況,我們容易搞混。針對針對多種情況結合我的理解,我提出了一句話「箭頭,定時和構造,特殊情況特殊看,普通調用看點號,後面有點不看前,然後就近原則判,最後剩下就是window”。 【相關推薦:javascript學習教學】
箭頭函數
箭頭函數的本身沒有this,所有不存在this改變,它捕捉外層的this使用
var name = "windowsName"; var a = { name: "Cherry", fn() { setTimeout(()=>{ console.log(this.name); },0) } } a.fn() //Cherry
解析: 首先物件a呼叫fn函數,所以fn函數的this指向物件a,然後箭頭捕捉外層this,那麼就不是setTimeout裡的this,而是fn函數的this,所以最後拿到物件a裡的name
計時器
對於延時函數內部的回呼函數的this指向全域物件window
var name = "windowsName"; var a = { name: "Cherry", fn() { setTimeout(function (){ console.log(this.name); },0) } } a.fn() //windowsName
解析: 首先物件a呼叫fn函數,然後這裡setTimeout裡的回呼函數是匿名函數,為普通的函數,那麼匿名函數中的this指向的就是window
var name = "windowsName"; var b={ name: "setTimeoutName" } var a = { name: "Cherry", fn() { setTimeout((function (){ console.log(this.name); }).bind(b),0) } } a.fn() //setTimeoutName
解析:首先物件a呼叫fn函數,然後這裡setTimeout裡的回呼函數是匿名函數,為普通的函數,那麼匿名函數中的this指向的就是window,但使用bind改變匿名函數的this指向為物件b,所以最後物件b裡的name
建構子
建構子中的this指向建立的實例對象,
注意:如果構造函數中返回一個對象,創建時不會有新的實例對象,而是這個返回的對象
function fn(){ this.age = 37; } var a = new fn(); console.log(a.age); // 37 a.age = 38; console.log(fn); // { this.age = 37; } console.log(a.age); // 38
解析:這裡我們透過構造函數創建實例對象a,相當於開闢一個新地方將構造函數內容複製過來,就有了a對象,這時候this指向的就是對象a,我們修改對象a中內容不影響構造函數
#點號判斷
透過.
判斷this指向,遵循就近原則
var a = { age:10, b: { age:12, fn(){ console.log(this.age); } } } a.b.fn(); //12
解析:物件a呼叫物件b的fn函數,fn函數前面有兩個.
,那麼最近的是物件b,所以fn函數的this指向的就是物件b,最後拿到的就是物件b的age
var a = { age:10, b: { age:12, fn(){ console.log(this.age); //undefined } } } var c = { age:20, } var d = { age:30, } a.b.fn.bind(c).bind(d)(); //20
解析:物件a呼叫物件b的fn函數接著使用bind改變this的指向,這時候fn前後前後都有.
,不看前面的.
,只用看後面的,然後最近的bind改變this指向為c,那麼此時fn函數的this指向的就是對象c,拿到的就是對象c的age
練習
function outerFunc() { console.log(this) // { x: 1 } function func() { console.log(this) // Window } func() } outerFunc.bind({ x: 1 })()
obj = { func() { const arrowFunc = () => { console.log(this._name) } return arrowFunc }, _name: "obj", } obj.func()() //obj func = obj.func func()() //undefined obj.func.bind({ _name: "newObj" })()() //newObj obj.func.bind()()() //undefined obj.func.bind({ _name: "bindObj" }).apply({ _name: "applyObj" })() //bindObj
#使用apply、call、bind 函數可以改變this的指向,上面this的例子中使用到
區別
thisArg , [ argsArray]
call(thisArg, arg1, arg2, ...)
apply和call函數差別在於this後面傳入的參數,apply中傳的是一個數組,而call中傳入的是展開的參數
bind(thisArg[ , arg1[, arg2[, ...]]])()
this
被指定為 bind()
的第一個參數,而其餘參數將作為新函數的參數,供呼叫時使用#如有錯誤,請大家指正! !感謝大家閱讀!
參考資料
https://juejin.cn/post/6946021671656488991#comment
#【相關影片教學推薦:web前端】
以上是你能搞懂JS的this指向問題嗎?看看這篇文章的詳細內容。更多資訊請關注PHP中文網其他相關文章!