What is "this" in JavaScript

前言

此次筆記根據姚偉揚老師的直播影片一次搞懂 JavaScript 的 #this、this 還有那個 this做的紀錄,有興趣的可以直接看影片,主講者講得很清楚,還會跟你互動。

this 是什麼

1
console.log(this);

直接印出thisGlobal物件,瀏覽器裡就是Window
為方便以下統稱Window

在一般函式裡

1
2
3
function a() {
console.log(this);
};

Q: 請問這個this是什麼?

A: 不知道

就是不知道!
因為…

函式裡的this是取決的函式是怎麼執行的

1. 直接執行函式

1
2
3
4
5
function a() {
console.log(this);
};

a(); //Window

this是Window

2. 作為物件的成員函式執行

1
2
3
4
5
6
7
8
const obj = {
name: 'object',
a() {
conosle.log(this)''
}
};

obj.a(); // obj

this是該物件

那這樣呢?

1
2
const b = obj.a;
b(); // Window

這就會回到第一個分類直接執行函式thisWindow

3. 作為 DOM 事件偵聽函式

1
<button id='btn'>btn</button>
1
2
3
4
5
function a() {
console.log(this);
};

btn.addEventListener('click',a); // DOM元素:<button id='btn'>btn</button>

this是該 DOM本身

注意

1
2
3
4
5
6
7
8
9
function MyClass() {
//...
};

const x = new MyClass();

x.addEventListener('loaded', function() {
console.log(this); //不一定
});

作為非DOM的偵聽,this是不一定

4. 作為建構函式

1
2
3
4
5
6
function A() {
console.log(this);
};

const a = new A();
console.log(this); // A{}

this是建構出來的實例

小測驗

1.

1
2
3
4
5
6
7
8
function () {
console.log(this); // ?
};

const obj = {};
obj.a = a();

obj.a();

反白看答案 => A: obj,作為obj的成員執行

2.

1
2
3
4
5
6
7
8
9
10
const obj = {
a() {
function b() {
console.log(this); // ?
}
b();
};
};

obj.a();

反白看答案 => A: Window,b是直接執行的

3.

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
function a() {
console.log(this); // ?
};

const obj = {a};

btn.addEventListener('click', obj.a);

反白看答案 => A: DOM元素 button

4.

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
function a() {
console.log(this); // ?
};

const obj = {
b(){
return function a() {
a();
};
},
};

btn.addEventListener('click', obj.b());

反白看答案 => A: Window, a函式是直接執行的

5.

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
8
9
const obj = {
b(){
return function a() {
console.log(this); // ?
};
},
};

btn.addEventListener('click', obj.b());

反白看答案 => A: DOM元素 button

6.

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
8
9
10
11
function a() {
console.log(this);
};

const obj = {
a(){
return a
},
};

btn.addEventListener('click', obj.a());

反白看答案 => A: DOM元素 button

ES6箭頭函式裡

1
2
3
const a = () => {
console.log(this);
};

箭頭函式內的this,永遠等於箭頭函式外的this。

也有人說箭頭函式在宣告時,this就決定了。

小測驗:

1.

1
<button id='btn'>btn</button>
1
2
3
4
5
const a = () => {
console.log(this); // ?
};

btn.addEventListener('click', a);

反白看答案 => A: Window

2.

1
2
3
4
5
6
7
const obj = {
a: () => {
console.log(this); // ?
},
};

obj.a();

反白看答案 => A: Window

3.

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
8
function a() {
const b = () => {
console.log(this); // ?
};
b();
};

btn.addEventListener('click', a);

反白看答案 => A: DOM元素 button

bind/apply/call的this

bind

強制把函式裡的this綁訂到目標物上,產生新的函式。

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
function a() {
console.log(this); //?
};

const b = a.bind(0);

btn.addEventListener('click', b);

thisNumber{0}

如果是這樣

1
2
3
4
5
const obj = {};

const b = a.bind(obj);

btn.addEventListener('click', b);

thisobj

必須留意的是,被bind綁訂的函式會創造出一個新的函式

a跟b是不同的函式,但他們內容是一樣的

補充

1
2
```htmlembedded=
<button id='btn'>btn</button>
1
2
3
4
5
6
7
8
function add(x, y) {
console.log(this); // Number{0}
console.log(x + y); // 10
};

const b = add.bind(0, 3, 4);

btn.addEventListener('click', b);

bind也可以綁訂參數

apply

bind有點像,但他是綁訂後直接執行

1
2
3
4
5
6
7
8
function add(x, y) {
console.log(this); // obj
console.log(x + y); //7
};

const obj = {};

add.apply(obj, [3, 4]);

call

apply一樣,接受參數方式不同

1
2
3
4
5
6
7
8
function add(x, y) {
console.log(this); // obj
console.log(x + y); //7
};

const obj = {};

add.call(obj, 3, 4); // 這裡不用寫成陣列

綁訂箭頭函式

1
<button id='btn'>btn</button>
1
2
3
4
5
6
7
8
9
const add = (x, y) => {
console.log(this);
console.log(x + y);
};

const b = add.bind(obj, 3, 4)
b();
add.apply(obj, [3, 4])
add.call(obj, 3, 4)

以上執行的都是Window
說明bind/apply/call對箭頭函式是無效的

參考資料

一次搞懂 JavaScript 的 #this、this 還有那個 this
以上筆記紀錄影片中的大部分的this,影片有提到Vue的this,有興趣看完整版點去看。