JavaScript(3):掌握箭頭函式,優雅簡約的程式寫作

Blog背景圖

箭頭函數是ES6的新語法,能夠有效縮短傳統函式寫法

傳統函式 VS 箭頭函式情境說明

  • 直接透過一個例子來進行比較更快瞭解,透過箭頭函式縮短傳統函式。
  • 情境:我想快速將陣列中的每個元素都變成兩倍(map對原陣列進行操作產生一個新的陣列)。

傳統函式

1
2
3
4
5
const arr = [1, 2, 3, 4, 5];
const resultarr = arr.map(function(item){
return item * 2
})
console.log(resultarr)

顯示如下:

1
[2,4,6,8,10]

箭頭函式

  • 方法1:省略function替換成箭頭函數的方式。
1
2
3
4
5
const arr = [1, 2, 3, 4, 5];
const resultarr = arr.map((item) =>{
return item * 2
})
console.log(resultarr)
  • 方法2:省略function + 省略return。
1
2
3
const arr = [1, 2, 3, 4, 5];
const resultarr = arr.map((item) => (item * 2))
console.log(resultarr)
  • 方法3:當確定僅有一個參數(item),不可為空或超過一個參數,可以省略成以下寫法。
1
2
3
const arr = [1, 2, 3, 4, 5];
const resultarr = arr.map(item => item * 2)
console.log(resultarr)

this指向差別-箭頭函式沒有自己的this指向

  • 當看到this的時候自動忽視包覆他的函式

傳統函式的this指向

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

顯示如下:

1
全域

案例1.回調函數遇到箭頭函式

  • 當看到this的時候自動忽視包覆他的函式(setTimeout),可以想像成this.name又變成在callName函式之下,因此這時候this.name就會從全域變數變成指向person物件下的name。
1
2
3
4
5
6
7
8
9
10
var name = '全域'
const person = {
name: '小明',
callName() {
setTimeout(() => {
console.log(this.name); // 2
});
},
}
person.callName();

顯示如下:

1
小明

案例2.傳統函式遇到箭頭函式(單層)

  • 使用箭頭函式會直接跳出當前包覆的function(callName),也就是目前並沒有人調用person本身,因此this會指向全域。
1
2
3
4
5
6
7
8
var name = '全域'
const person = {
name: '小明',
callName: () => {
console.log(this.name);
},
}
person.callName();

顯示如下:

1
全域

案例3.傳統函式遇到箭頭函式(雙層)

  • this.name跳脫包覆他的callName函式,變成直接在callMe下面,因此callMe被person呼叫使用,this將會指向person。
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();

顯示如下:

1
小明

this指向實戰作法,讓this取得正確的值

  • 回調函式使用傳統函式的寫法一般指向全域
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();

顯示如下:

1
全域

修改方式1.利用其他變數取代當前this

  • 透過在fn使用變數儲存當前this位置指向fn,在回調函式中使用該變數以讓this指向obj4,取得物件 4的值。
1
2
3
4
5
6
7
8
9
10
11
var someone = '全域';
var obj4 = {
someone: '物件 4',
fn() {
const that = this
setTimeout(function () {
console.log(that.someone);
});
}
}
obj4.fn();

顯示如下:

1
物件 4

修改方式2.使用箭頭函數

  • 透過箭頭函數忽視函式setTimeout,讓this變成在fn函式下,this就會指向使用fn的obj4,進而取得obj4下的someone。
1
2
3
4
5
6
7
8
9
10
var someone = '全域';
var obj4 = {
someone: '物件 4',
fn() {
setTimeout(() => {
console.log(this.someone);
});
}
}
obj4.fn();

顯示如下:

1
物件 4