在我們看見的各種介紹如何判斷this的指向方法中,"this的最終指向的是那個呼叫它的物件" 這句話被視作核心,但是面對多種多樣的情況,我們容易搞混。針對針對多種情況結合我的理解,我提出了一句話 「箭頭,定時和構造,特殊情況特殊看,普通呼叫看點號,後面有點不看前,然後就近原則判,最後剩下就是window」。【相關推薦:】
箭頭函數
箭頭函數的本身沒有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
【相關視訊教學推薦:】
以上就是你能搞懂JS的this指向問題嗎?看看這篇文章的詳細內容,更多請關注TW511.COM其它相關文章!