JavaScript ES6箭頭函數(shù)使用指南
胖箭頭函數(shù)(Fat arrow functions),又稱(chēng)箭頭函數(shù),是一個(gè)來(lái)自ECMAScript 2015(又稱(chēng)ES6)的全新特性。有傳聞?wù)f,箭頭函數(shù)的語(yǔ)法=>,是受到了CoffeeScript 的影響,并且它與CoffeeScript中的=>語(yǔ)法一樣,共享this上下文。
箭頭函數(shù)的產(chǎn)生,主要由兩個(gè)目的:更簡(jiǎn)潔的語(yǔ)法和與父作用域共享關(guān)鍵字this。接下來(lái),讓我們來(lái)看幾個(gè)詳細(xì)的例子。
新的函數(shù)語(yǔ)法
傳統(tǒng)的JavaScript函數(shù)語(yǔ)法并沒(méi)有提供任何的靈活性,每一次你需要定義一個(gè)函數(shù)時(shí),你都必須輸入function () {}。
CoffeeScript如今之所以那么火,有一個(gè)不可忽略的原因就是它有更簡(jiǎn)潔的函數(shù)語(yǔ)法。更簡(jiǎn)潔的函數(shù)語(yǔ)法在有大量回調(diào)函數(shù)的場(chǎng)景下好處特別明顯,讓我們從一個(gè)Promise鏈的例子看起:
function getVerifiedToken(selector) { return getUsers(selector) .then(function (users) { return users[0]; }) .then(verifyUser) .then(function (user, verifiedToken) { return verifiedToken; }) .catch(function (err) { log(err.stack); }); }
以下是使用新的箭頭函數(shù)語(yǔ)法進(jìn)行重構(gòu)后的代碼:
function getVerifiedToken(selector) { return getUsers(selector) .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack)); }
以下是值得注意的幾個(gè)要點(diǎn):
function和{}都消失了,所有的回調(diào)函數(shù)都只出現(xiàn)在了一行里。
當(dāng)只有一個(gè)參數(shù)時(shí),()也消失了(rest參數(shù)是一個(gè)例外,如(...args) => ...)。
當(dāng){}消失后,return關(guān)鍵字也跟著消失了。單行的箭頭函數(shù)會(huì)提供一個(gè)隱式的return(這樣的函數(shù)在其他編程語(yǔ)言中常被成為lamda函數(shù))。
這里再著重強(qiáng)調(diào)一下上述的最后一個(gè)要求。僅僅當(dāng)箭頭函數(shù)為單行的形式時(shí),才會(huì)出現(xiàn)隱式的return。當(dāng)箭頭函數(shù)伴隨著{}被聲明,那么即使它是單行的,它也不會(huì)有隱式return:
const getVerifiedToken = selector => { return getUsers() .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack)); }
如果我們的函數(shù)內(nèi)只有一條聲明(statement),我們可以不寫(xiě){},這樣看上去會(huì)和CoffeeScript中的函數(shù)非常相似:
const getVerifiedToken = selector => getUsers() .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack));
你沒(méi)有看錯(cuò),以上的例子是完全合法的ES6語(yǔ)法。當(dāng)我們談?wù)撝话粭l聲明(statement)的箭頭函數(shù)時(shí),這并不意味著這條聲明不能夠分成多行寫(xiě)。
這里有一個(gè)坑,當(dāng)忽略了{(lán)}后,我們?cè)撛趺捶祷乜諏?duì)象({})呢?
const emptyObject = () => {}; emptyObject(); // ?
不幸的是,空對(duì)象{}和空白函數(shù)代碼塊{}長(zhǎng)得一模一樣。以上的例子中,emptyObject的{}會(huì)被解釋為一個(gè)空白函數(shù)代碼塊,所以emptyObject()會(huì)返回undefined。如果要在箭頭函數(shù)中明確地返回一個(gè)空對(duì)象,則你不得不將{}包含在一對(duì)圓括號(hào)中(({})):
const emptyObject = () => ({}); emptyObject(); // {}
下面是一個(gè)更完整的例子:
function () { return 1; } () => { return 1; } () => 1 function (a) { return a * 2; } (a) => { return a * 2; } (a) => a * 2 a => a * 2 function (a, b) { return a * b; } (a, b) => { return a * b; } (a, b) => a * b function () { return arguments[0]; } (...args) => args[0] () => {} // undefined () => ({}) // {}
this
JavaScript中this的故事已經(jīng)是非常古老了,每一個(gè)函數(shù)都有自己的上下文。以下例子的目的是使用jQuery來(lái)展示一個(gè)每秒都會(huì)更新的時(shí)鐘:
$('.current-time').each(function () { setInterval(function () { $(this).text(Date.now()); }, 1000); });
當(dāng)嘗試在setInterval的回調(diào)中使用this來(lái)引用DOM元素時(shí),很不幸,我們得到的只是一個(gè)屬于回調(diào)函數(shù)自身上下文的this。一個(gè)通常的解決辦法是定義一個(gè)that或者self變量:
$('.current-time').each(function () { var self = this; setInterval(function () { $(self).text(Date.now()); }, 1000); });
但當(dāng)使用胖箭頭函數(shù)時(shí),這個(gè)問(wèn)題就不復(fù)存在了。因?yàn)樗划a(chǎn)生屬于它自己上下文的this:
$('.current-time').each(function () { setInterval(() => $(this).text(Date.now()), 1000); });
arguments變量
箭頭函數(shù)與普通函數(shù)還有一個(gè)區(qū)別就是,它沒(méi)有自己的arguments變量:
function log(msg) { const print = () => console.log(arguments[0]); print(`LOG: ${msg}`); } log('hello'); // hello
再次重申,箭頭函數(shù)沒(méi)有屬于自己的this和arguments。但是,你仍可以通過(guò)rest參數(shù),來(lái)得到所有傳入的參數(shù)數(shù)組:
function log(msg) { const print = (...args) => console.log(args[0]); print(`LOG: ${msg}`); } log('hello'); // LOG: hello
關(guān)于yield
箭頭函數(shù)不能作為generator函數(shù)使用。
最后
箭頭函數(shù)是我最喜歡的ES6特性之一。使用=>來(lái)代替function是非常便捷的。但我也曾見(jiàn)過(guò)只使用=>來(lái)聲明函數(shù)的代碼,我并不認(rèn)為這是好的做法,因?yàn)?>也提供了它區(qū)別于傳統(tǒng)function,其所獨(dú)有的特性。我個(gè)人推薦,僅在你需要使用它提供的新特性時(shí),才使用它:
當(dāng)只有一條聲明(statement)語(yǔ)句時(shí),隱式return。
需要使用到父作用域中的this。
本文詳細(xì)說(shuō)明了JavaScript ES6新特性之一的箭頭函數(shù)的使用方法和一些注意事項(xiàng),大家在使用時(shí)一定要注意,箭頭函數(shù)用好了是非常快捷的,如果用不好的話也是非常令人頭痛的
相關(guān)文章
關(guān)于什么是javascript模塊化以及為何使用模塊化開(kāi)發(fā)
這篇文章主要介紹了關(guān)于什么是javascript模塊化以及為何使用模塊化開(kāi)發(fā),模塊化是一種軟件開(kāi)發(fā)的設(shè)計(jì)模式,它將一個(gè)大型的軟件系統(tǒng)劃分成多個(gè)獨(dú)立的模塊,每個(gè)模塊都有自己的功能和接口,需要的朋友可以參考下2023-04-04JavaScript中isPrototypeOf、instanceof和hasOwnProperty函數(shù)的用法詳解
本文詳細(xì)講解了JavaScript中isPrototypeOf、instanceof和hasOwnProperty函數(shù)的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06js onkeypress與onkeydown 事件區(qū)別詳細(xì)說(shuō)明
本文將詳細(xì)介紹js onkeypress與onkeydown 事件區(qū)別:一個(gè)放開(kāi)一個(gè)沒(méi)有放開(kāi),onkeydown先于onkeypress 發(fā)生,需要的朋友可以參考下2012-12-12JavaScript 基礎(chǔ)篇之對(duì)象、數(shù)組使用介紹(三)
對(duì)象我們?cè)谇懊嬉埠?jiǎn)單介紹過(guò),它是一種將多個(gè)數(shù)據(jù)值集中在一個(gè)單元的東西,使用名字來(lái)存取,它是一個(gè)無(wú)序的屬性集合2012-04-04JavaScript中將數(shù)組進(jìn)行合并的基本方法講解
這篇文章主要介紹了JavaScript中將數(shù)組進(jìn)行合并的基本方法講解,包括快速合并多個(gè)數(shù)組的方法,需要的朋友可以參考下2016-03-03