【探祕ES6】系列專欄(七):箭頭函數

ES6做爲新一代JavaScript標準,已正式與廣大前端開發者見面。爲了讓你們對ES6的諸多新特性有更深刻的瞭解,Mozilla Web開發者博客推出了《ES6 In Depth》系列文章。CSDN已獲受權,將持續對該系列進行翻譯,組織成【探祕ES6】系列專欄,供你們學習借鑑。本文爲該系列的第七篇。 
javascript

本文接下來說述的是有關ES6箭頭函數(Arrow functions)的使用。前端

熱身java

箭頭符號在JS中一直扮演着重要的角色。在JS教程裏,一開始都會介紹如何使用箭頭括號來加註釋。例如:es6

<script language="javascript">  
<!--  
  document.bgColor = "brown";  // red  
// -->  
</script>

舊版瀏覽器接收的是兩個不支持的標籤和一句註釋,只有新版瀏覽器纔會識別這是JS代碼。

爲了處理這種奇怪的表達方式,瀏覽器的JS引擎會把<!—識別爲一行註釋的開始位置。這種處理機制一直沿用至今,如今於Node中也適用。除此以外,-->還能夠做爲遞增/減的操做符,例如while(n-->0) //n遞減至0。瀏覽器

咱們先回顧下箭頭符號的通常用法:函數

  • <!-- 單行註釋學習

  • -->  遞增/減的操做符this

  • <=   小於等於spa

  • =>   ?.net

=>是ES6中新的用法,也就是本節要講述的內容。

隨處可見的函數式表達

在JS中頗有意思的地方是當咱們須要調用函數時,只需在運行代碼中的恰當位置添加就能夠了。例如要對按鈕的點擊作出響應,能夠這樣寫:

$("#confetti-btn").click(function (event) {  
  playTrumpet();  
  fireConfettiCannon();  
});

在JS開始盛行前,這樣的代碼是使人奇怪的,由於不少語言當時都沒有相似的寫法。除了1958年List語言的lambda(匿名)函數有函數表達式功能,C++、Python、C#等語言長時間裏都是沒有的。到了如今,lambda已經隨處可見了,這多虧了JS的功勞。例如,
// A very simple function in six languages.  
function (a) { return a > 0; } // JS  
[](int a) { return a > 0; }  // C++  
(lambda (a) (> a 0))  ;; Lisp  
lambda a: a > 0  # Python  
a => a > 0  // C#  
a -> a > 0  // Java

新的箭頭語法

ES6引入了新的箭頭函數編寫方式。

// ES5  
var selected = allJobs.filter(function (job) {  
  return job.isSelected();  
});  
  
// ES6  
var selected = allJobs.filter(job => job.isSelected());

當須要編寫一個簡單的單一參數函數時,能夠採用箭頭函數來書寫,標識名=>表達式。這樣就能夠省卻function和return的輸入,還有括號,分號等。

當須要編寫一個含有多個參數的函數時,只要把相關參數用括號包起來就行了。

// ES5  
var total = values.reduce(function (a, b) {  
  return a + b;  
}, 0);  
  
// ES6  
var total = values.reduce((a, b) => a + b, 0);

我認爲這是最簡潔的書寫格式。

箭頭函數的功用與Underscore.js和immutable等庫的功能相似,immutable的示例文檔中所有都是使用ES6來編寫的,所以使用了大量的箭頭函數。

除了函數樣式編寫,箭頭函數還能夠包含區塊語句而不單單是單一表達式。例如:

// ES5  
$("#confetti-btn").click(function (event) {  
  playTrumpet();  
  fireConfettiCannon();  
});

ES6的寫法爲:
// ES6  
$("#confetti-btn").click(event => {  
  playTrumpet();  
  fireConfettiCannon();  
});

this是什麼?

普通函數與箭頭函數有個微小的不一樣點。箭頭函數沒有本身的this值,其this值是經過繼承其它傳入對象而得到的。

JS是如何處理this的呢?這可不是個簡單的問題。其中不論函數有沒有真的須要處理this,函數都是會接收到的。你曾經寫過以下代碼嗎?

{  
  ...  
  addAll: function addAll(pieces) {  
    var self = this;  
    _.each(pieces, function (piece) {  
      self.add(piece);  
    });  
  },  
  ...  
}

這裏,其實你想寫的內聯函數僅僅是this.add(piece)。然而內聯函數不會繼承外部函數的this值。在內聯函數中,this的值是window或undefined。臨時變量self用於向內聯函數傳入外部this值。

在ES6中,若是遵循以下原則則可避免相似的作法:

  • 使用非箭頭函數來處理由object.method()語法調用的方法。由於它們會接收到來自調用者的有意義的this值。

  • 在其它場合都使用箭頭函數。

// ES6  
{  
  ...  
  addAll: function addAll(pieces) {  
    _.each(pieces, piece => this.add(piece));  
  },  
  ...  
}

何時使用箭頭函數

ES6箭頭函數在Firefox、Babel、Traceur、TypeScript等項目都有使用。在1936年,Alonzo Church和Alan Turing一塊兒開發了強大的數學計算機模型,人們習慣把它稱爲圖靈機。Church編寫了名爲λ-calculus的模型,當時他發現須要在系統使用到「函數」。

這是一個結合Church想法的「程序」示例:

fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))

JS中可表示爲:

var fix = f => (x => f(v => x(x)(v)))  
               (x => f(v => x(x)(v)));

這個故事告訴咱們,箭頭函數能夠幫助打破陳規,重新的角度來思考問題。藉助箭頭函數,ES6將會變得更好更強大。(譯者:伍昆 責編:陳秋歌)

原文連接:ES6 In Depth: Arrow functions

本譯文遵循Creative Commons Attribution Share-Alike License v3.0 

相關文章
相關標籤/搜索