this指向問題

haqiu發表於2019-04-10

this指向誰?

this永遠指向最終呼叫的函式所在的物件

① this指向的,永遠只可能是物件!

② this指向誰,永遠不取決於this寫在哪!而是取決於函式在哪呼叫。

③ this指向的物件,我們稱之為函式的上下文context,也叫函式的呼叫者。

1. 當直接呼叫函式時,this指向window

  function Obj () {
    console.log(this)
  }
  Obj() // window
複製程式碼

2. 函式為物件屬性時,this指向該物件

  function Obj () {
    console.log(this)
  } 
  let obj = {
    name: 'hello',
    where: Obj
  }
  obj.where() // {name: "hello", where: ƒ}
複製程式碼

3. 建構函式中,this指向例項化物件

  function Obj () {
    console.log(this)
  }  
  let obj = new Obj() // Obj{}
複製程式碼

4. 在setTimeout和setInterval,this永遠指向window

  function Obj () {
    setTimeout(function () {
  	  console.log(this)
    }, 100)
  } 
  let obj = {
    name: 'hello',
    where: Obj
  }
  obj.where() // window
複製程式碼

為何在setTimeout和setInterval中this永遠指向window呢?下面專門瞭解一下

setTimeout和setInterval中this指向問題

由setTimeout()呼叫的程式碼執行在與所在函式完全分離的執行環境上。這會導致,這些程式碼中包含的 this 關鍵字在非嚴格模式會指向 window (或全域性)物件,嚴格模式下為 undefined

  function Obj () {
    this.checkThis = function () {
      console.log(this)
    },
    this.checkThisLast = function () {
      setTimeout(function() {
        console.log(this)
      },100)
    }
  }
  let obj = new Obj()
  obj.checkThis() // Obj{}
  obj.checkThisLast() // window
複製程式碼

如何解決setTimeout和setInterval中this的指向問題呢?

變數儲存this

  function Obj () {
    let self = this, // this繫結給一個變數
    this.checkThis = function () {
      console.log(this)
    },
    this.checkThisLast = function () {
      setTimeout(function() {
        console.log(self)
      },100)
    }
  }
  let obj = new Obj()
  obj.checkThis() // Obj{}
  obj.checkThisLast() // Obj{}
複製程式碼

箭頭函式

箭頭函式不會建立自己的this,它只會從自己的作用域鏈的上一層繼承this

  • 指向定義時所在的作用域,而不是指向執行時所在的作用域。
  function Obj () {
    this.checkThis = function () {
      console.log(this)
    },
    this.checkThisLast = function () {
      setTimeout(() => {
        console.log(this)
      },100)
    }
  }
  let obj = new Obj() 
  obj.checkThis() // obj{}
  obj.checkThisLast() // obj{}
複製程式碼

bind()繫結

bind()用法是將函式繫結到物件上,會建立新的函式,函式體內的this值會被繫結到傳入bind()的首個引數;f.bind(obj)相當於obj.f(),則f()的this指向obj

  • call(),apply()可以實現同樣this繫結,但call()、apply()呼叫後立即執行,apply()需要接收陣列引數
  function Obj () {
    this.checkThis = function () {
      console.log(this)
    },
    this.checkThisLast = function () {
      setTimeout(function () {
        console.log(this)
      }.bind(this),100)
    }
  }
  let obj = new Obj()
  obj.checkThis() // obj{}
  obj.checkThisLast() // obj{}
複製程式碼

相關文章