首先不得不承認(rèn)颗胡,箭頭函數(shù)是ES6中非常受歡迎的一個(gè)功能毫深,它提出了一種新的書寫方式來(lái)簡(jiǎn)潔的定義函數(shù)。
舉例說(shuō)明:
ES5:
function timesTwo(params) {
return params * 2;
}
timesTwo(4); //8
使用ES6箭頭函數(shù):
const timesTwo = params => params * 2;
timesTwo(4); //8
代碼更簡(jiǎn)短毒姨,而且可以省略大括號(hào)和return語(yǔ)句(在沒(méi)有代碼塊的情況下)哑蔫。與ES5相比,為何箭頭函數(shù)的表現(xiàn)方式可以有如此大的不同呢弧呐?
各種變量
你可能見(jiàn)過(guò)箭頭函數(shù)有很多種的使用方式闸迷,比如:
- 沒(méi)有參數(shù)
如果沒(méi)有參數(shù),可以在=>之前放置一個(gè)空括號(hào)
const a = () => 42
a() //42
實(shí)際上俘枫, 我們甚至不需要括號(hào):
const a = _ => 42
a() //42
- 一個(gè)參數(shù)
在這種情況下腥沽,括號(hào)是可選的:
const a = x => 42 || const a = (x) => 42
a() || a(1) //42
- 多個(gè)參數(shù)
此時(shí),必須加括號(hào):
const a = (x, y) => 42
a(1, 2) //42
- 語(yǔ)句(而非表達(dá)式)
在最基本的形式中鸠蚪,表達(dá)式會(huì)產(chǎn)生一個(gè)值今阳,而語(yǔ)句代表著一種待執(zhí)行的行為,比如if else語(yǔ)句茅信。使用箭頭函數(shù)時(shí)盾舌,語(yǔ)句必須有大括號(hào)。而一旦使用了花括號(hào)汹押,就必須添加return 關(guān)鍵字矿筝。
在箭頭函數(shù)中使用if語(yǔ)句的例子:
var feedTheCat = (cat) => {
if (cat === 'hungry') {
return 'Feed the cat';
} else {
return 'Do not feed the cat';
}
}
- 代碼塊
如果你的代碼在一個(gè)塊中,就必須顯式的使用return語(yǔ)句棚贾。
var addValues = (x, y) => {
return x + y
}
- 對(duì)象字面量
如果需要返回一個(gè)對(duì)象窖维,就要使用()
包裹榆综。這會(huì)迫使解釋器去評(píng)估括號(hào)內(nèi)的內(nèi)容,能夠正確的返回對(duì)象铸史。
const obj = x =>({ y: x })
obj(1) //{y: 1}
匿名語(yǔ)法
箭頭函數(shù)是匿名的鼻疮,這會(huì)帶來(lái)一些問(wèn)題:
- 難以debug
出現(xiàn)錯(cuò)誤時(shí),無(wú)法追蹤該方法名稱或具體的執(zhí)行行號(hào)(個(gè)人不是很認(rèn)同琳轿,箭頭函數(shù)相當(dāng)于匿名函數(shù)判沟,將其地址賦值給變量后不是一樣的使用么)
- 沒(méi)有自引用
如果你需要自引用(比如遞歸),使用箭頭函數(shù)難以實(shí)現(xiàn)崭篡。
主要的優(yōu)點(diǎn): 不用顯式綁定this
在函數(shù)表達(dá)式中挪哄,this是根據(jù)它被調(diào)用的上線文綁定到不同的值的,但是在箭頭函數(shù)中琉闪,this是直接被綁定到詞法作用域的迹炼。this 就是指向包含著箭頭函數(shù)的這段代碼。
舉個(gè)栗子:
//ES5
var obj = {
id: 42,
counter: function counter() {
setTimeout(function() {
console.log(this.id);
}.bind(this), 1000);
}
};
在上段代碼中颠毙,bind(this)
不能省略斯入,否則this將指向window,從而this.id打印出undefined.
//ES6
var obj = {
id: 42,
counter: function counter() {
setTimeout(() => {
console.log(this.id);
}, 1000);
}
};
箭頭函數(shù)不能綁定到this關(guān)鍵字蛀蜜,所以它會(huì)在詞法上上升一個(gè)作用域刻两,然后在定義的作用域中使用這個(gè)值。
何時(shí)不該使用箭頭函數(shù)滴某?
經(jīng)過(guò)上邊幾個(gè)例子磅摹,應(yīng)該也能意識(shí)到箭頭函數(shù)并不能完全替代常規(guī)的函數(shù)。那么何時(shí)我們不該使用箭頭函數(shù)呢壮池?
- 對(duì)象方法
var cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
調(diào)用cat.jumps()
后偏瓤,cat.lives
并不會(huì)減1。這是因?yàn)閠his就沒(méi)有被綁定到這個(gè)對(duì)象上椰憋,而是從父級(jí)作用域繼承了this
.
- 具有動(dòng)態(tài)context的回調(diào)函數(shù)
當(dāng)context需要?jiǎng)討B(tài)改變的時(shí)候厅克,箭頭函數(shù)通常不是正確的選擇。比如在一個(gè)事件句柄中:
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
如果我們點(diǎn)擊按鈕橙依,我們會(huì)得到一個(gè)TypeError证舟。這是因?yàn)閠his不是綁定到按鈕,而是綁定到了它的父級(jí)窗骑。
- 當(dāng)使用箭頭函數(shù)使你的代碼可讀性降低(難以知道這段代碼將發(fā)生什么)的時(shí)候
何時(shí)使用箭頭函數(shù)女责?
箭頭函數(shù)最能發(fā)揮功力的場(chǎng)景就是需要this綁定到context,而非函數(shù)本身的時(shí)候创译。我還尤其喜歡在map
或者reduce
方法中使用箭頭函數(shù)抵知,這使得程序可讀性更強(qiáng)。