JavaScript中關於this指向的4種狀況

對不少前端開發者來講,JavaScript語言的this指向是一個使人頭疼的問題。先看下面這道測試題,若是你能實現並解釋緣由,那本文對你來講價值不大,能夠直接略過。前端

**開篇測試題:**嘗試實現註釋部分的Javascript代碼,可在其餘任何地方添加更多代碼(如不能實現,說明一下不能實現的緣由):瀏覽器

let Obj = function (msg) {
    this.msg = msg
    this.shout = function () {
      alert(this.msg)
    }
    this.waitAndShout = function () {
      // 隔5秒後執行上面的shout方面
      setTimeout(function () {
        let self = this
        return function () {
          self.shout()
        }
      }.call(this), 5000)
    }
  }
複製代碼

題目的參考答案在文末,但我不建議你直接查看答案,而是先閱讀並思考文章的中的知識點。app

1、在對象屬性中的this指向問題

  • 對象的屬性是函數,那麼函數中的this指向的是對象自己,即例子中的obj
var obj = {
    x: 123,
    fn: function () {
      console.log(this) // {x: 123, fn: ƒ}
      console.log(this.x)  // 123
    }
  }
  obj.fn()
複製代碼
  • 對象的屬性是函數,函數內部還有函數,那麼這個二級(及以上)函數的this指向的是window
var obj = {
    x: 456,
    fn: function () {
      console.log('fn', this) // {x: 456, fn: ƒ}
      var f1 = function () {
        console.log('fn.f1', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
        console.log(this.x) // undefined
        var f2 = function () {
          console.log('fn.f2', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
        }
        f2()
      }
      f1()
    }
  }
  obj.fn()
複製代碼

從上面的例子,咱們能夠總結出,對象屬性中,嵌套超過一級及以上的函數,this指向都是window函數

2、構造函數中的this指向問題

  • 構造函數中的一級函數,this指向經過構造函數new出來的實例(例子中的person
var Person = function () {
    this.name = 'linlif'
    this.fn = function () {
      console.log('fn', this) // {name: "linlif", fn: ƒ}
    }
  }
  var person = new Person()
  person.fn()
複製代碼
  • 構造函數中的二級(及以上)函數,this指向的是window
var Person = function () {
    this.name = 'linlif'
    this.fn = function () {
      console.log('fn', this) // {name: "linlif", fn: ƒ}
      var f2 = function () {
        console.log('f2', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
        var f3 = function () {
          console.log('f3', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
        }
        f3()
      }
      f2()
    }
  }
  var person = new Person()
  person.fn()
複製代碼

從上面的例子,咱們能夠總結出,構造函數中,嵌套超過一級及以上的函數,this指向的都是windowpost

3、全局上下文環境中this指向問題

全局上下文環境,this指向瀏覽器的window對象,例如:測試

// 全局的this
  console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
  console.log(this === window) // true

 // 全局的普通函數
 var global = function () {
    console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
  }
  global()
複製代碼

4、call()和apply()對this指向的影響

使用call()方法後,this指向call()方法的參數。使用apply()的結果和call()是一致的,這裏不作贅述。關於call()apply()用法的區別,請自行查詢相關資料。ui

// 改變調用對象爲gObj
  var gObj = {
    name: 'gName'
  }
  var aaa = function () {
    console.log(this) // {name: "gName"}
    console.log(this.name) // gName
  }
  aaa.call(gObj)
  
  // 改變調用對象爲window
  var name = 'global'
  var bbb = function () {
    console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
    console.log(this.name) // global
  }
  bbb.call(this)
複製代碼

總結:這就是一些關於this的指向問題的我的理解了,若是發現不妥之處,歡迎在評論區指出,或者私信我。this

彩蛋 開篇測試題的參考答案,僅供參考!(有意思的地方:題目中,函數名的第一個字母大寫,已經暗示這是一個構造函數)spa

let Obj = function (msg) {
    this.msg = msg
    this.shout = function () {
      alert(this.msg)
    }
    this.waitAndShout = function () {
      // 隔5秒後執行上面的shout方面
      setTimeout(function () {
        let self = this
        return function () {
          self.shout()
        }
      }.call(this), 5000)
    }
  }

  let obj = new Obj('msg')
  obj.waitAndShout()
複製代碼

本篇完。code

相關文章
相關標籤/搜索