❒ 大部分 this 的運作模式
先判斷程式碼是傳統函式或箭頭函式
- 傳統函式中的
this 只與調用方式有關,與怎麼定義 this 無關 。
- 呼叫函式時,前面有任何物件
this 就會指向它,如果 this 前沒有任何物件會指向全域。( 下方會有範例 )
setTimeout 為 callback function 是 simple call 的一種形式,在傳統函式寫法下 this 會指向全域,為了避免 setTimeout 的 this 指向全域可使用「 箭頭函式 」或是「 指向其他變數 」。( 最後範例 8 )
- 箭頭函式沒有自己的
this,會看外層函式的 this 指向。
- 宣告方式不同 (
var、const、let ) ,this 也會不同,要留意。
❒ #1 一個函式中包含多少參數
1 2 3 4 5 6
| var a = '全域' function fn(params) { console.log(params, this, window, arguments); debugger; } fn(1, 2, 3);
|

// 執行 debugger ,開發者工具會跳到 Sources 區域 ▲
console.log(params, this, window, arguments); → 中為運行函數本身就可以執行的參數內容
params 為外部傳入的參數。
this 目前是指向 windows ,但實際在運作時可能會有很多種不同的指向,此指向會影響在使用框架時指到哪,如果想要指向特定的元件但卻指向錯誤,就會出錯。
window 瀏覽器本身就存在的全域變數。
arguments 傳統函式會帶入的參數,為類陣列會帶入所有傳入的參數內容。
- 程式中
fn(1, 2, 3); 有三個參數 arguments 會列出所有參數值。
❒ #2 this 的指向為何
1 2 3 4 5 6 7 8
| var obj = { name: '小明', fn: function(params) { console.log(params, this, window, arguments); } } obj.fn(1 , 2 , 3);
|
fn: 的函式程式碼與 #1 範例相同,但卻只有 this 有所不同。
- 1 為外部傳入的參數
{name: "小明", fn: ƒ} 為 this。

❒ #3 注意:this 的指向相當複雜,大部分情境只需要了解其中一種即可(95%)
傳統函式中的 this 只與調用方式有關,與怎麼定義 this 無關 。
大部分情境只須了解其中一種,請看下方 #4 this 的各種運用變化 | this 的判斷方式
1 2 3 4 5 6 7 8 9
| var someone = '全域'; function callSomeone() { console.log(this.someone); } callSomeone();
|
❒ #4 this 的各種運用變化 | this 的判斷方式
this 的判斷 : ( 此判斷方式以傳統函式為主,箭頭函式的判斷法請看 #5 this 陷阱 )
- 呼叫函式時,前面有任何物件
this 就會指向它 ( 例 : #4 );
- 呼叫函式時,如果前方沒任何物件就會指向全域 ( 例 : #3 的 simple call )。
範例 1
1 2 3 4 5 6 7 8 9 10 11 12 13
| var someone = '全域'; function callSomeone() { console.log(this.someone); } var obj = { someone: '物件', callSomeone() { console.log(this.someone); } } obj.callSomeone();
|

// 呼叫函式時,前面有任何物件 this 就會指向它 ▲
範例 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var someone = '全域'; function callSomeone() { console.log(this.someone); }
var obj2 = { someone : '物件2', callSomeone } obj2.callSOmeone();
|
- 變數 obj2 裡的
callSomeone 指向 function callSomeone()。
- 呼叫函式時,前面有任何物件
this 就會指向它,所以 this 指向變數 obj2。
範例 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var someone = '全域'; function callSomeone() { console.log(this.someone); } var wrapObj = { someone: '外層物件', callSomeone, innerObj: { someone: '內層物件', callSomeone, } } wrapObj.callSomeone(); wrapObj.innerObj.callSomeone();
|
- 下方程式碼中,外層與內層的物件
callSomeone 皆使用函式 callSomeone()。
- 呼叫函式時,前面有任何物件
this 就會指向它。
wrapObj.callSomeone(); → 所以 this 指向 wrapObj,輸出 外層物件。
wrapObj.innerObj.callSomeone(); → 所以 this 指向 innerObj,輸出 內層物件。
範例 4
1 2 3 4 5 6 7 8 9 10 11
| var someone = '全域'; function callSomeone() { console.log(this.someone); } var obj3 = { someone: `物件 3`, fn() { callSomeone(); } } obj3.fn();
|
this 與怎麼定義無關,只和調用方式有關,調用這個 fn() 內的 callSomeone() 函式時前方沒有看到任何物件,就屬於 simple call 會指向全域。
obj3.fn(); → output 全域
- ‼️ 注意 : 通常會於物件下的方式調用 this,不會使用 simple call 方式去取得
this,結果可能會不如預期,這邊解說範例用。

範例 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var someone = '全域'; function callSomeone() { console.log(this.someone); } var obj4 = { someone: '物件 4', fn() { setTimeout(function () { console.log(this.someone); }); } } obj4.fn();
|
範例 6. 請問以下 this 的結果是甚麼 ?
1 2 3 4 5 6 7 8 9
| var obj = { data: { myName: 'hexschool', }, getName: function () { console.log(this.data.myName); } } obj.getName();
|
getName: function () 為傳統函式,傳統函式的 this 都會看前方呼叫它的是誰。
obj.getName(); 結果為 hexschool。
範例 7. 請問以下 this 的結果是甚麼 ?
1 2 3 4 5 6 7 8 9
| var obj = { data: { myName: 'hexschool', }, getName: () => { console.log(this.data.myName); } } obj.getName();
|
- 箭頭函式沒有自己的
this。它會看外層函式作用域中的 this 指向,如果外層沒有函式則會指向全域。
這邊全域沒東西,所以結果如下。
obj.getName(); 結果為 TypeError: Cannot read property 'myName' of undefined。
範例 8
1 2 3 4 5 6 7 8 9 10 11 12
| var myName = '小明'; var obj = { myName: '小美', x: function () { var myName = '小王'; setTimeout(function () { console.log(this.myName); }, 0); }, y: '2', } obj.x();
|
setTimeout(function (){}) 為 callback function ( 大部分屬於 simple call 形式 ),會指向全域。
但要注意,如果 callback function 這邊改為箭頭函式指向就會改變。
obj.getName(); 結果為 小明。
參考資訊