大部分只是整理筆記,歡迎隨意看看

0%

JS - This 是什麼

本篇用來整理自己所理解的 JavaScript 中的 this

This 是誰

this 的指向主要與怎麼呼叫有關,最簡單的辨識方式就是,
執行函式時前方不帶物件的話就會指向 window 也就是全域,
如果前方有物件的話就會指向前方的物件,但要注意,不管有幾個物件,只會往前找一個,
重點不在怎麼定義的,而是執行的當下前方有沒有物件。

呼叫的方式的差異

1. 直接呼叫

1
2
3
4
5
6
var name = '全域';
function callThis() {
var name = '區域';
console.log(this.name);
};
callThis(); // 全域

使用直接呼叫的話 this 會指向全域,因為執行函式時前方並沒有任何的物件。

2. 呼叫物件中的函式

1
2
3
4
5
6
7
8
9
var name = '全域';
function callThis() {
console.log(this.name);
};
var area = {
name: '區域',
callThis: callThis,
};
area.callThis(); // 區域

本例中呼叫函式的方式為area.callThis(),所以只要找前方的物件就可以知道 this 是誰,
本例中的 this 就是位於物件 area 內的 name,也就是區域

3. 立即函式

1
2
3
4
5
var name = '全域';
(function () {
var name = '區域';
console.log(this.name);
})(); // 全域

使用立即函式的話,因為前方沒有物件,因此也會指向全域

4. 物件裡的物件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var name = '全域';
function callThis() {
console.log(this.name);
};
var area = {
name: '第一層',
callThis: callThis,
secArea: {
name: '第二層',
callThis: callThis,
},
};
area.callThis(); // 第一層
area.secArea.callThis(); // 第二層

一樣的原則,this 會根據呼叫的方式而改變,
area.callThis()會讓 this 指向物件 area,所以是第一層,
area.secArea.callThis()會讓 this 指向 secArea,所以是第二層,
記得一開始說過嗎不管有幾個物件,只會往前找一個

5. 重新定義

1
2
3
4
5
6
7
8
9
var name = '全域';
var area = {
name: '區域',
callThis: function() {
console.log(this.name);
},
};
var callThis = area.callThis;
callThis(); // 全域

將函式重新定義一個變數,並直接呼叫變數,
這時候因為前方沒有物件,所以這裡的 this 一樣會指向全域。

閉包

這篇不說明閉包的概念,僅說明閉包對 this 的影響。
至於閉包對 this 有什麼影響呢?
閉包不會影響 this 的指向,一樣是根據呼叫時前方有沒有物件來決定。

call、apply、bind

call

參考資料

1
2
3
4
5
6
7
8
9
10
11
function callThis() {
console.log(this.name);
};

var name = '全域';
var area = {
name: '區域',
};

callThis.call(undefined); // 全域
callThis.call(area); // 區域

call 可以直接指定 this 的指向,第一個帶入的參數就是 this 的指向。
而為什麼帶入undefined會指向 window 呢?
因為在非嚴苛模式時, null、undefined 將會被置換成全域變數。
參考

apply

與 call 類似,差別在傳入的參數用陣列表示。

bind

1
2
var hello = callName.bind(this 的指向);
hello(原本要帶入的參數);

也是與 call、apply 類似,不過寫法不太一樣,如上。

箭頭函式

箭頭函式沒有 this,他會去找外層作用域的 this,
因此可以透過先定義 this 來避免找不到 this。

本篇參考資料