JavaScript ES6箭頭函數(shù)使用指南
胖箭頭函數(shù)(Fat arrow functions),又稱箭頭函數(shù),是一個來自ECMAScript 2015(又稱ES6)的全新特性。有傳聞?wù)f,箭頭函數(shù)的語法=>,是受到了CoffeeScript 的影響,并且它與CoffeeScript中的=>語法一樣,共享this上下文。
箭頭函數(shù)的產(chǎn)生,主要由兩個目的:更簡潔的語法和與父作用域共享關(guān)鍵字this。接下來,讓我們來看幾個詳細(xì)的例子。
新的函數(shù)語法
傳統(tǒng)的JavaScript函數(shù)語法并沒有提供任何的靈活性,每一次你需要定義一個函數(shù)時,你都必須輸入function () {}。
CoffeeScript如今之所以那么火,有一個不可忽略的原因就是它有更簡潔的函數(shù)語法。更簡潔的函數(shù)語法在有大量回調(diào)函數(shù)的場景下好處特別明顯,讓我們從一個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ù)語法進(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));
}
以下是值得注意的幾個要點(diǎn):
function和{}都消失了,所有的回調(diào)函數(shù)都只出現(xiàn)在了一行里。
當(dāng)只有一個參數(shù)時,()也消失了(rest參數(shù)是一個例外,如(...args) => ...)。
當(dāng){}消失后,return關(guān)鍵字也跟著消失了。單行的箭頭函數(shù)會提供一個隱式的return(這樣的函數(shù)在其他編程語言中常被成為lamda函數(shù))。
這里再著重強(qiáng)調(diào)一下上述的最后一個要求。僅僅當(dāng)箭頭函數(shù)為單行的形式時,才會出現(xiàn)隱式的return。當(dāng)箭頭函數(shù)伴隨著{}被聲明,那么即使它是單行的,它也不會有隱式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),我們可以不寫{},這樣看上去會和CoffeeScript中的函數(shù)非常相似:
const getVerifiedToken = selector => getUsers() .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack));
你沒有看錯,以上的例子是完全合法的ES6語法。當(dāng)我們談?wù)撝话粭l聲明(statement)的箭頭函數(shù)時,這并不意味著這條聲明不能夠分成多行寫。
這里有一個坑,當(dāng)忽略了{(lán)}后,我們該怎么返回空對象({})呢?
const emptyObject = () => {};
emptyObject(); // ?
不幸的是,空對象{}和空白函數(shù)代碼塊{}長得一模一樣。以上的例子中,emptyObject的{}會被解釋為一個空白函數(shù)代碼塊,所以emptyObject()會返回undefined。如果要在箭頭函數(shù)中明確地返回一個空對象,則你不得不將{}包含在一對圓括號中(({})):
const emptyObject = () => ({});
emptyObject(); // {}
下面是一個更完整的例子:
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)是非常古老了,每一個函數(shù)都有自己的上下文。以下例子的目的是使用jQuery來展示一個每秒都會更新的時鐘:
$('.current-time').each(function () {
setInterval(function () {
$(this).text(Date.now());
}, 1000);
});
當(dāng)嘗試在setInterval的回調(diào)中使用this來引用DOM元素時,很不幸,我們得到的只是一個屬于回調(diào)函數(shù)自身上下文的this。一個通常的解決辦法是定義一個that或者self變量:
$('.current-time').each(function () {
var self = this;
setInterval(function () {
$(self).text(Date.now());
}, 1000);
});
但當(dāng)使用胖箭頭函數(shù)時,這個問題就不復(fù)存在了。因?yàn)樗划a(chǎn)生屬于它自己上下文的this:
$('.current-time').each(function () {
setInterval(() => $(this).text(Date.now()), 1000);
});
arguments變量
箭頭函數(shù)與普通函數(shù)還有一個區(qū)別就是,它沒有自己的arguments變量:
function log(msg) {
const print = () => console.log(arguments[0]);
print(`LOG: ${msg}`);
}
log('hello'); // hello
再次重申,箭頭函數(shù)沒有屬于自己的this和arguments。但是,你仍可以通過rest參數(shù),來得到所有傳入的參數(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特性之一。使用=>來代替function是非常便捷的。但我也曾見過只使用=>來聲明函數(shù)的代碼,我并不認(rèn)為這是好的做法,因?yàn)?>也提供了它區(qū)別于傳統(tǒng)function,其所獨(dú)有的特性。我個人推薦,僅在你需要使用它提供的新特性時,才使用它:
當(dāng)只有一條聲明(statement)語句時,隱式return。
需要使用到父作用域中的this。
本文詳細(xì)說明了JavaScript ES6新特性之一的箭頭函數(shù)的使用方法和一些注意事項(xiàng),大家在使用時一定要注意,箭頭函數(shù)用好了是非常快捷的,如果用不好的話也是非常令人頭痛的
相關(guān)文章
Javascript typeof與instanceof的區(qū)別
JavaScript 中 typeof 和 instanceof 常用來判斷一個變量是否為空,或者是什么類型的。但它們之間還是有區(qū)別的,需要的朋友可以參考下2016-10-10
使用JavaScript 實(shí)現(xiàn)各種跨域的方法
本篇文章是對在JavaScript中實(shí)現(xiàn)各種跨域方法的介紹。需要的朋友參考下2013-05-05
caller和callee的區(qū)別介紹及演示結(jié)果
caller返回一個函數(shù)的引用,這個函數(shù)調(diào)用了當(dāng)前的函數(shù);callee放回正在執(zhí)行的函數(shù)本身的引用,它是arguments的一個屬性,感興趣的你可以參考下或許可以幫助到你2013-03-03
javascript 構(gòu)造函數(shù)方式定義對象
這篇文章主要介紹了javascript 構(gòu)造函數(shù)方式定義對象的方法及示例,需要的朋友可以參考下2015-01-01

