淺談js的this指向與解決思路

weixin_33968104發表於2018-11-20

有一定js開發經驗的人一定會踩過this的坑。this這個問題也是老生常談了。今天就來總結一下this到底有哪些坑,以及對應的解決思路。
先舉個常見的坑:

var obj = {
a: 1,
b: function () {
      console.log(this.a); // 1
      setTimeout(function(){
         console.log(this.a); // undefined
      }, 1000)
    }
}

第一個 console.log(this.a) 理解沒問題,this.a 就是指向obj,因為誰是最後呼叫者的,就指向誰, 請記住:

this 永遠指向最後呼叫它的那個物件

同樣理解第二個,外面包裹了一個 setTimeout 方法,setTimeout是一個任務派發器,它實際上就是派發任務的,任務就是1秒鐘後執行的這個方法,而setTimeout實際上就是window物件下的一個方法,1秒鐘後執行的整個方法同樣也是掛載在window物件下,而window物件根本沒有定義window.a這個變數,所以是undefined;
怎麼解決呢?

// 1;
var obj = {
a: 1,
b: function () {
      console.log(this.a); // 1
      var _this = this; // 拿到這個物件的上下文
      setTimeout(function(){
         console.log(_this .a); // 1
      }, 1000)
    }
}

第一種方法: 在setTimeout外面拿到當前物件的this賦值到一個變數_this, 然後在任務方法裡面就可以正確拿到obj這個物件的引用了。

// 2 箭頭函式,箭頭函式是沒有this的
var obj = {
a: 1,
b: function () {
      console.log(this.a); // 1
      setTimeout(() =>{
         console.log(this .a); // 1
      }, 1000)
    }
}

第二種方法:箭頭函式需要記著這句話:

箭頭函式中沒有 this 繫結,必須通過查詢作用域鏈來決定其值,如果箭頭函式被非箭頭函式包含,則 this 繫結的是最近一層非箭頭函式的 this,否則,this 為 undefined

// 3 ,  bind() 繫結this到另外一個物件
var obj = {
a: 1,
b: function () {
      console.log(this.a); // 1
      setTimeout(function(){
         console.log(this.a); // 1
      }.bind(this), 1000)
    }
}

第三種方法:就是通過bind()這個方法主動改變這個任務方法的引用。

相關文章