首頁  >  文章  >  web前端  >  你能搞懂JS的this指向問題嗎?看看這篇文章

你能搞懂JS的this指向問題嗎?看看這篇文章

青灯夜游
青灯夜游轉載
2022-03-25 11:05:521928瀏覽

你能搞懂JavaScript的this指向問題嗎?以下這篇文章帶大家聊聊這令人煩惱的this指向問題,希望對大家有幫助!

你能搞懂JS的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

#使用apply、call、bind 函數可以改變this的指向,上面this的例子中使用到

區別

thisArg , [ argsArray] call(thisArg, arg1, arg2, ...)

apply和call函數差別在於this後面傳入的參數,apply中傳的是一個數組,而call中傳入的是展開的參數

bind(thisArg[ , arg1[, arg2[, ...]]])()

  • 然後bind函數建立的是新的函數,需要手動去呼叫
  • 這個新函數的 this 被指定為 bind() 的第一個參數,而其餘參數將作為新函數的參數,供呼叫時使用

#如有錯誤,請大家指正! !感謝大家閱讀!

參考資料

https://juejin.cn/post/6946021671656488991#comment

#【相關影片教學推薦:web前端

以上是你能搞懂JS的this指向問題嗎?看看這篇文章的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除