0%

JS 核心觀念筆記 - 什麼是 this

this

1
2
3
4
var vm = "全域";

function callName() {}
callName();

上方有一個全域變數與函式,函式內沒有任何東西,當呼叫此函式時,執行堆疊會看到作用域中產生 this 並指向 window。

this

而這個 this 的指向與如何呼叫此函式的方式有很大的關連性。

修改函式內容:

1
2
3
4
5
6
var vm = "全域";

function callName() {
console.log(this.vm); //全域
}
callName();

此時函式中執行的 console 中是指向全域的變數,所以得到的是 vm 的值,由此可知函式中會自動升成 this。

this 的基本觀念

  • 不管是全域或是特定函式,都可以直接調用 this 這個關鍵字,而 this 會在每個執行環境都會存在,所以會容易被誤會為指向該函式本身。但函式能提供的方法很有限,故比較不會使用 this 調用函式本身,this 比較常被拿來指向該物件,但因為函式本身也是物件,所以這是造成誤解的原因。
  • 每個環境都有自己的 this 關鍵字。
  • this 與函式如何宣告沒有關連性,僅與呼叫方式有關。
  • 嚴格模式下,簡易呼叫會有很大的改變。

影響函式 this 的調用方式

  • 做為物件方法(最常使用)。
  • 簡易呼叫(絕大多數的呼叫方式,要避免使用此呼叫方式來調用 this)。
  • bind,apply,call 將 this 綁定的特定方法。
  • new 一個物件(建構式的運算子)。
  • DOM 事件處理器。
  • 箭頭函式(ES6)。

this 的用途

  • 可略過函式的定義方式,改依據執行的方式取用特定物件。

this 物件方法的調用(最常使用)

  • this 與函式如何宣告沒有關連性,僅與呼叫方法有關。
  • 物件的方法調用時,僅需要關注的是哪一個物件下呼叫。

thisObj

示意圖如上,掌握此概念就能使用大部份的 this。

範例一

1
2
3
4
5
6
7
8
9
10
11
12
var vm = "全域";

function callName() {
console.log(this.vm);
}

var ming = {
vm: "區域",
callName: callName,
};

ming.callName(); //區域

上方有兩個物件,一個是函式,一個是物件,執行是由 ming 這個物件來呼叫函式,所以得到的 vm 直為區域變數的值。

範例二

若今天在函式中還有一個函式,如前面所說,不需要管函式怎麼定義,只要知道是哪個物件呼叫 this,第一個函式呼叫的結果就會是區域,第二個函式呼叫後是在 name 被呼叫,所以所得的值會是 name 裡面的 vm。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var vm = "全域";

function callName() {
console.log(this.vm);
}

var ming = {
vm: "區域",
callName: callName,
name: {
vm: "區域中的區域",
callName: callName,
},
};

ming.callName(); //區域
ming.name.callName(); //區域中的區域

範例三

今天在物件中宣告一個函式,並且宣告一個變數來存取物件中函式的值,但因為函式宣告前面並沒有使用物件,所以 this 會指向全域(window),所以得出來的值會是最外層全域的 vm 的值。

1
2
3
4
5
6
7
8
9
10
var vm = "全域";

var ming = {
vm: "區域",
callName: function () {
console.log(this.vm);
},
};
var callName = ming.callName;
callName(); //全域

資料參考

  1. 鐵人賽:JavaScript 的 this 到底是誰?
  2. JavaScript This 系列文:this 為什麼指向 window
  3. JavaScript This 系列文:this 與物件的關係
  4. 重新認識 JavaScript: Day 20 What’s “THIS” in JavaScript (鐵人精華版)