0%

JS核心篇-箭頭函式

箭頭函式簡寫寫法

原本的函式內容是像下面這樣

1
2
3
4
const test = function (someone) {
return '我是' + someone
}
test('小明')

step1. 將function取代成箭頭

1
2
3
4
const test = (someone) => {
return '我是' + someone
}
test('小明')

step2. 箭頭函式的內容是一表達式
這是什麼意思呢,就是代表箭頭函式裡面只有要回傳東西沒有其他內容了
那這樣的話,我們就可以縮寫成下面這樣,把return拿掉。

1
2
const test = (someone) => '我是' + someone
test('小明')

step3. 若箭頭函式的參數只有一個
若箭頭函式的參數只有一個,我們就可以省略參數旁邊的括號,但要注意喔!!
只有在參數只有一個的時候才能這樣操作,若它是沒有參數 或參數是兩個以上的時候,
是不能省略小括號的。
所以,上面的例子可以改寫成這樣

1
2
const test = someone => '我是' + someone
test('小明')

箭頭函式 v.s 傳統函式

沒有arguments的參數

一般傳統的函式是有arguments來儲存傳入的參數。
要特別注意的是arguments是一個類陣列,代表它不能使用陣列的全部功能。
那箭頭函式是沒有arguments這個參數,但是,我們還是想要取用傳入的參數的話
要怎麼辦呢?
我們可以用其餘參數

1
2
3
4
const test = (...argu) => {
console.log(argu)
}
test(1, 2, 3, 4, 5, 6, 7)

這樣的話我們就可以取用傳入的參數內容,而且這個其餘參數argu是真正的陣列,
所以,它可以使用陣列本身就有的方法。

this綁定的不同

首先,箭頭函式沒有屬於自己的this
當箭頭函式內有調用this的時候,這個this會跟箭頭函式外層作用域的this相同

1
2
3
4
5
6
7
8
9
10
11
12
var myName = '全域'
const person = {
myName: '小明',
callMyName: function () {
console.log('1', this.myName)
setTimeout(() => {
console.log('2', this.myName)
console.log('3', this)
}, 1000)
}
}
person.callMyName()

上面這個範例分別會出現
‘1’ ‘小明’
‘2’ ‘小明’
‘3’ person物件
如此,我們就可以看得出來,在箭頭函式內調用this就會是在定義該箭頭函式的作用域的this對象。

接著,我們在改寫一下上面的範例,把callMyName也改成箭頭函式寫法

1
2
3
4
5
6
7
8
9
10
11
12
var myName = '全域'
const person = {
myName: '小明',
callMyName: () => {
console.log('1', this.myName)
setTimeout(() => {
console.log('2', this.myName)
console.log('3', this)
}, 1000)
}
}
person.callMyName()

這個時候,你會發現內部的this全部都指向window了,這是因為callMyName在定義的時候,
變數person是屬於window物件的屬性,所以,callMyName的外層作用域的this是指向window
最終,才會造成callMyName內部的this都是指向window的結果。

this不同,導致DOM的this也會指向不同位置

你可以看到上面這個例子,我們是用箭頭函式來撰寫監聽事件裡面的東西。
裡面的this就會是window,而不是p段落本身。

無法透過.call, .apply, .bind來重新賦予this

由上面這個範例,你看我們刻意利用call來傳入family物件,但是,console的結果,在this的部分,就不會是family物件,而是window物件
這是因為fn本身是屬於window物件的屬性。

箭頭函式無法當成建構函式使用

以上這個範例,你可以看到我們利用箭頭函式來創一個建構函式,但是,我們要印出這個箭頭函式的prototype,會發現是undefined
另外,我們對b變數來利用這個箭頭函式來當建構函式來創物件,但會出現該箭頭函式不是建構式的錯誤。
由此,我們就可以看的出來箭頭函式不能當作建構式用。

箭頭函式常見問題

在這一篇我們是要記錄一下在使用箭頭函式的時候,會遇到的問題。

回傳物件

1
2
const test = () => ({data:1})
console.log(test()) // {data:1}

上面這個範例,看到我們要在箭頭函式中回傳一個物件,我們必須要特別在這個回傳物件的外面特別用小括號把它包起來,才能成功把這個物件成功回傳回來。

規則式中使用箭頭函式

1
2
3
let num = 0
let ming = num || (() => 1)
console.log(ming())

你可以看到範例中,我們在規則式裡面有回傳一個箭頭函式,但是,你依樣要用小括號將這個箭頭函式包起來,才能成功回傳它喔~

箭頭函式的this指向

箭頭函式本身是沒有this的,它的this是該箭頭函式外層作用域的this
那這個錯誤,很常發生於我們在撰寫框架的時候,會遇到。

1
2
3
4
5
6
7
8
var app = new Vue({
data: {
num: 1
}
created: () => {
console.log(this.num)
}
})

上面這個範例,我們將created改寫成箭頭函式,那這個時候的this就會是指向window而不是app這個物件喔。

原型的prototype用箭頭函式來定義

上面這範例,你可以看到我們對建構式的原型新增建構函式,那最終我們呼叫這個建構函式,並引出當下的this對象,結果是window

箭頭函式實戰用法

ex1: 陣列的map使用箭頭函式來撰寫

上面可以看到map我們是使用箭頭函式來撰寫,也有一樣的效果。

ex2: 陣列的reduce用箭頭函式撰寫

你可以看到我們全部都用箭頭函式來撰寫,可以把程式碼精簡成一段程式碼而已。

ex3. 用ajax取得資料,並搭配箭頭函式撰寫

你可以看到上面的範例內部在用ajax來取得遠端資料,我們就用箭頭函式來取得內部的資料,那也因為箭頭函式沒有自己的this,所以,這個this使指向該箭頭函式外層的作用域,也就是person物件囉。