JS 觀念 - 箭頭函式的 this 指向差異

JS 觀念 - 箭頭函式的 this 指向差異

傳統函式與箭頭函式寫法差別

傳統函式

取有餘數的值(單數)

1
2
3
4
5
6
7
const arr = [1, 2, 3, 4, 5];

const filterArr = arr.filter(function(item) {
return item % 2 // 只要結果為真值就會回傳
})

console.log(filterArr); // [ 1,3,5 ]

箭頭函式

取有餘數的值(單數)

1
2
const filterArr = arr.filter(item => item % 2);
console.log(filterArr);

箭頭函式可以將 function 移除掉改成箭頭,接著把 {} 、 return 移除掉,改成單行。
箭頭函式它會自動帶上 return
當參數只有一個時,可以把 () 拿掉,當參數有 2 個或沒有參數則不可省略


箭頭函式與傳統函式的 this 指向有何差別?

傳統函式

1
2
3
4
5
6
7
8
9
10
11
12
var name = '全域'
const person = {
name: '小胖',
callName: function () {
console.log('1', this.name); // 1 小胖
setTimeout(function () {
console.log('2', this.name); // 2 simple call 指向全域的 name
console.log('3', this); // 3 指向 window
}, 10);
},
}
person.callName();

箭頭函式

箭頭函式沒有自己的 this

1
2
3
4
5
6
7
8
9
10
11
12
var name = '全域'
const person = {
name: '小胖',
callName: function () {
console.log('1', this.name); // 1 小胖
setTimeout(()=> {
console.log('2', this.name); // 2 小胖
console.log('3', this); // 3 指向 person 物件
}, 10);
},
}
person.callName();

如果 setTimeout function 採箭頭函式,那麼 this 就要往外層的 callName function 看。
外層的 callName function 的 this 指向哪裡,那麼內層 setTimeout function 的 this 就指向哪裡。


箭頭函式陷阱

1.

1
2
3
4
5
6
7
8
var name = '全域'
const person = {
name: '小胖',
callName: () => {
console.log(this.name);
},
}
person.callName(); // 全域

因為 callName function 找不到外層函式,所以指向全域

2.

1
2
3
4
5
6
7
8
9
10
11
var name = '全域'
const person = {
name: '小胖',
callMe() {
const callName = () => {
console.log(this.name);
};
callName();
}
}
person.callMe();

callName function 的外層函式是 callMe,callMe 的 this 指向 person ,this.name = 小胖


常見用法

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

var obj4 = {
someone: '物件 4',
fn() {
setTimeout(function () {
console.log(this.someone);
});
}
}

obj4.fn();

如何讓 setTimeout function 取得 obj4 中的 someone ?

方法 1. this 先指向其他變數

1
2
3
4
5
6
7
8
9
10
11
12
13
var someone = '全域';

var obj4 = {
someone: '物件 4',
fn() {
const vm = this;
setTimeout(function () {
console.log(vm.someone); // 確保取得 obj4 物件,不受干擾
});
}
}

obj4.fn();

方法 2. 使用箭頭函式,讓 this 去找外層的

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

var obj4 = {
someone: '物件 4',
fn() {
setTimeout(()=> { // 改成箭頭函式
console.log(this.someone);
});
}
}

obj4.fn();