
🌟 JavaScript this 指向跟調用方式相關
一個函式中包含多少參數
1 2 3 4 5
| var a = '全域' function fn(params) { console.log(params, this, window, arguments); } fn(100, 200, 300)
|
- 每個 Function 都擁有params及arguments
- params(參數):參數是函式定義中所列出的變數
- arguments(引數):引數是當我們呼叫函式時傳遞給它的值
- [100, 200, 300]
- 這個是類陣列(Array-like):意思就是他不是真的陣列,有一些方法他並無法使用,雖然他可以查看長度,以及變更參數的值,但是他不是純陣列。
- this(隱含的引數):根據調用的方式指向的位置不同(這邊是全域變數也就是 window)
- window:預設的全域變數。
- 接著讓我們來了解不同情況的 this 的指向(以調用的方式為主)
- 這邊 this 是 callSomeone 的孩子,本身自己調用函式的情況下 this 會指向全域(window)變數,也就是全域變數的 someone。
1 2 3 4 5
| var someone = '全域'; function callSomeone() { console.log(this.someone); } callSomeone();
|
顯示如下:
案例 1.傳統函式 this 指向
- 當前案例 this 是 callSomeone 的小孩。
- 調用的方式改成透過 obj 去調用這個 callSome,這時候 this 會改指向前面的這個怪叔叔,也就是 obj,所以這邊的 this 已經不是 window,已經改變成 obj,自然 this.someone 就會變成 obj 裡面的 someone。
1 2 3 4 5 6 7 8
| var someone = '搗蛋鬼' var obj = { someone: '物件', callSomeone() { console.log(this.someone); } } obj.callSomeone();
|
顯示如下:
案例 2.引用傳統函式 this 指向(小小變形一下)
- 雖然原本定義在 obj 裡面的 function 變成引用外面的 function,但調用的方式依然是 obj2.callSomeone(),傳統函式的情況大多符合這種規則。
1 2 3 4 5 6 7 8 9
| var someone = '全域'; function callSomeone() { console.log(this.someone); } var obj2 = { someone: '物件2', callSomeone } obj2.callSomeone();
|
顯示如下:
案例 3.夾帶兩層函式的 this 指向
- 這邊可以看到 wrapObj.callSomeone()這個是由 wrapObj 調用,因此 this 會指向 wrapObj 這個物件,自然就會將 this.someone 定義成外層物件。
- 而 wrapObj.innerObj.callSomeone()調用的人改變成 innderObj,因此調用的 this.someone 將會定義成 innerObj 裡面的內層物件。
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();
|
顯示如下:
特殊案例 1.間接使用 this 函式
- 我們來看看特別一些的案例,記清楚剛剛說過 this 只取決於調用他的人是誰,callSomeone 前面並沒有人使用它,因此他的 this 會指向全域(陷阱題)。
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();
|
顯示如下:
特殊案例 2.setTimeout 回調函式
- 大部分傳統函式的情況下,遇到回調函式,this 會指向全域變數,因此 this.someone 會變成搗蛋鬼。
1 2 3 4 5 6 7 8 9 10
| var someone = '搗蛋鬼'; var obj4 = { someone: '物件 4', fn() { setTimeout(function () { console.log(this.someone); }); } } obj4.fn();
|
顯示如下: