JavaScript ES6箭頭函數指南

前言

胖箭頭函數(Fat arrow functions),又稱箭頭函數,是一個來自ECMAScript 2015(又稱ES6)的全新特性。有傳聞說,箭頭函數的語法=>,是受到了CoffeeScript 的影響,而且它與CoffeeScript中的=>語法同樣,共享this上下文。編程

箭頭函數的產生,主要由兩個目的:更簡潔的語法和與父做用域共享關鍵字this。接下來,讓咱們來看幾個詳細的例子。數組

新的函數語法

傳統的JavaScript函數語法並無提供任何的靈活性,每一次你須要定義一個函數時,你都必須輸入function () {}CoffeeScript現在之因此那麼火,有一個不可忽略的緣由就是它有更簡潔的函數語法。更簡潔的函數語法在有大量回調函數的場景下好處特別明顯,讓咱們從一個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); });
}

如下是使用新的箭頭函數語法進行重構後的代碼:函數

function getVerifiedToken(selector) {
  return getUsers(selector)
    .then(users => users[0])
    .then(verifyUser)
    .then((user, verifiedToken) => verifiedToken)
    .catch(err => log(err.stack));
}

如下是值得注意的幾個要點:this

  • function{}都消失了,全部的回調函數都只出如今了一行裏。spa

  • 當只有一個參數時,()也消失了(rest參數是一個例外,如(...args) => ...)。rest

  • {}消失後,return關鍵字也跟着消失了。單行的箭頭函數會提供一個隱式的return(這樣的函數在其餘編程語言中常被成爲lamda函數)。code

這裏再着重強調一下上述的最後一個要求。僅僅當箭頭函數爲單行的形式時,纔會出現隱式的return。當箭頭函數伴隨着{}被聲明,那麼即便它是單行的,它也不會有隱式return對象

const getVerifiedToken = selector => {
  return getUsers()
    .then(users => users[0])
    .then(verifyUser)
    .then((user, verifiedToken) => verifiedToken)
    .catch(err => log(err.stack));
}

若是咱們的函數內只有一條聲明(statement),咱們能夠不寫{},這樣看上去會和CoffeeScript中的函數很是類似:blog

const getVerifiedToken = selector =>
  getUsers()
    .then(users => users[0])
    .then(verifyUser)
    .then((user, verifiedToken) => verifiedToken)
    .catch(err => log(err.stack));

你沒有看錯,以上的例子是徹底合法的ES6語法。當咱們談論只包含一條聲明(statement)的箭頭函數時,這並不意味着這條聲明不可以分紅多行寫。

這裏有一個坑,當忽略了{}後,咱們該怎麼返回空對象({})呢?

const emptyObject = () => {};
emptyObject(); // ?

不幸的是,空對象{}和空白函數代碼塊{}長得如出一轍。。以上的例子中,emptyObject{}會被解釋爲一個空白函數代碼塊,因此emptyObject()會返回undefined。若是要在箭頭函數中明確地返回一個空對象,則你不得不將{}包含在一對圓括號中(({})):

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

JavaScriptthis的故事已是很是古老了,每個函數都有本身的上下文。如下例子的目的是使用jQuery來展現一個每秒都會更新的時鐘:

$('.current-time').each(function () {
  setInterval(function () {
    $(this).text(Date.now());
  }, 1000);
});

當嘗試在setInterval的回調中使用this來引用DOM元素時,很不幸,咱們獲得的只是一個屬於回調函數自身上下文的this。一個一般的解決辦法是定義一個that或者self變量:

$('.current-time').each(function () {
  var self = this;
 
  setInterval(function () {
    $(self).text(Date.now());
  }, 1000);
});

但當使用胖箭頭函數時,這個問題就不復存在了。由於它不產生屬於它本身上下文的this

$('.current-time').each(function () {
  setInterval(() => $(this).text(Date.now()), 1000);
});

arguments變量

箭頭函數與普通函數還有一個區別就是,它沒有本身的arguments變量:

function log(msg) {
  const print = () => console.log(arguments[0]);
  print(`LOG: ${msg}`);
}
 
log('hello'); // hello

再次重申,箭頭函數沒有屬於本身的thisarguments。可是,你仍能夠經過rest參數,來獲得全部傳入的參數數組:

function log(msg) {
  const print = (...args) => console.log(args[0]);
  print(`LOG: ${msg}`);
}
 
log('hello'); // LOG: hello

關於yield

箭頭函數不能做爲generator函數使用。

最後

箭頭函數是我最喜歡的ES6特性之一。使用=>來代替function是很是便捷的。但我也曾見過只使用=>來聲明函數的代碼,我並不認爲這是好的作法,由於=>也提供了它區別於傳統function,其所獨有的特性。我我的推薦,僅在你須要使用它提供的新特性時,才使用它:

  • 當只有一條聲明(statement)語句時,隱式return

  • 須要使用到父做用域中的this

相關文章
相關標籤/搜索