1. 程式人生 > >前端讀者 | 嗨,你知道this嗎

前端讀者 | 嗨,你知道this嗎

本文來自 @position_柚子,地址:https://juejin.im/post/5995c7a76fb9a0247a60c407

在平時的程式碼中,相信大家經常用到 this,可是你真的明白此 this 真的是你認為的 this 嗎?今天柚子君總結了一下平時用到的 this 的場景,大家走過路過不要錯過啊~

首先咱們先來看一下《JavaScript 高階程式設計》上是怎麼說的。

this 物件是在執行時基於函式的執行環境繫結的:在全域性函式中,this 等於 windows,而當函式被作為某個物件的方法呼叫時,this 等於那個物件。

還有一種情況,在《深入理解 ES6》一書中寫道:

如果箭頭函式被非箭頭函式包含,則 this 繫結的是最近一層非箭頭函式的 this,且不能通過 call()、apply() 或 bind() 方法來改變 this 的值。

首先看一下非箭頭函式的情況:

一、普通函式呼叫

這是一個普通的函式宣告,在這種情況下,this 是指向 window 的:

var test = '哈哈哈';
function thisHandler() {
    console.log('test:',this.test,'this:',this);
}
thisHandler() // test: 哈哈哈 this: window

其實上面的程式碼就相當於 window

呼叫 thisHandler(),所以這時 this 指向 window

var b = '哈哈哈';
function thisHandler() {
    console.log('b:',this.b,'this:',this);
}
window.thisHandler() // b: 哈哈哈 this: window

二、作為物件的方法呼叫

當作為物件的方法被呼叫時,this 這時就指向呼叫它的物件。

var thisHandler = {
  name: "柚子",
  test: function(){
    console.log('my name:',this.name); 
  }
}
thisHandler.test() // my name: 柚子

再來一個栗子:

var thisHandler = {
  name: "柚子",
  fn: {
    name: '芒果',
    test: function() {
       console.log('my name:',this.name); 
    }
  }
}
thisHandler.fn.test() // my name: 芒果

這時 this 指向的是物件 fn 了,所以,關於物件呼叫這一點明白了嗎,如果明白了,那沒關係,接著看下一個強化題:

var name = '柚子'
var thisHandler = {
  name: "芒果",
  fn: {
    name: '糖果',
    test: function(){
      console.log('my name:',this.name); 
    }
  }
}
var testHandler = thisHandler.fn.test
testHandler()

這裡是一秒鐘分割線

噠噠噠,答對了,這裡的 this 指向的 window,那麼這是為什麼呢,哪位小盆友來回答一下。舉手:

上面說到了,this 指向的是最後呼叫它的物件,第一步是賦值給了 testHandler,最後執行的那一句相當於 window.testHandler()。所以這裡的 this 指向的是 window。最後輸出的就是 my name: 柚子

噠噠噠,真聰明,來闖下一關~

三、建構函式的呼叫

var name = '柚子'
function Bar() {
  this.name = '芒果'
}

var handlerA = new Bar();
console.log(handlerA.name);  // 芒果
console.log(name) // 柚子

其實要明白為什麼會是這樣一個結果,咱們就要來聊聊 new 做了哪些事情。

  • 建立類的例項。這步是把一個空的物件的 __proto__ 屬性設定為 Bar.prototype
  • 初始化例項。函式 Bar 被傳入引數並呼叫,關鍵字 this 被設定為該例項。
  • 返回例項。

弄明白了 new 的工作內容,自然而然的也明白了上面輸出的原因。

Bar() 中的 this 指向物件 handlerA,並不是全域性物件。

四、apply / call 呼叫

使用 apply 方法可以改變 this 的指向。如果這個函式處於非嚴格模式下,則指定為 nullundefined 時會自動指向全域性物件(瀏覽器中就是window物件)。

var name = '芒果';
var thisHandler = {
  name: "柚子",
  test: function(){
    console.log('my name:',this.name); 
  }
};

thisHandler.test(); //  my name: 柚子
thisHandler.test.apply(); // my name: 芒果

四、箭頭函式

在《深入理解 ES6》一書中可以知道箭頭函式和普通函式的一個不同之處就在於 this 的繫結。

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

var name = '柚子'
var thisHandler = {
  name: '芒果',
  test:() => {
    console.log('my name:',this.name,'this:',this); 
  }
}

thisHandler.test(); // my name: 柚子 this: Window

這時 this 不是指向 thisHandler,而是 Window

關於 this 的使用和體會還是要在平時運用中理解,先了解其原理,那麼在使用的時候就如魚得水啦。