ES6作為新一代JavaScript標準,已正式與廣大前端開發者見面。為了讓大家對ES6的諸多新特性有更深入的了解,Mozilla Web開發者博客推出了《ES6 In Depth》系列文章。CSDN已獲授權,將持續對該系列進行翻譯,組織成【探秘ES6】系列專欄,供大家學習借鑒。本文為該系列的第七篇。
本文接下來講述的是有關ES6箭頭函數(Arrow functions)的使用。
熱身
箭頭符號在JS中一直扮演著重要的角色。在JS教程里,一開始都會介紹如何使用箭頭括號來加注釋。例如:
[js] view plaincopy
<script language="javascript">
<!--
document.bgColor = "brown"; // red
// -->
</script>
舊版瀏覽器接收的是兩個不支持的標簽和一句注釋,只有新版瀏覽器才會識別這是JS代碼。
為了處理這種奇怪的表達方式,瀏覽器的JS引擎會把<!—識別為一行注釋的開始位置。這種處理機制一直沿用至今,現在于Node中也適用。除此之外,-->還可以作為遞增/減的操作符,例如while(n-->0) //n遞減至0。
我們先回顧下箭頭符號的一般用法:
<!-- 單行注釋
--> 遞增/減的操作符
<= 小于等于
=> ?
=>是ES6中新的用法,也就是本節要講述的內容。
隨處可見的函數式表達
在JS中很有意思的地方是當我們需要調用函數時,只需在運行代碼中的恰當位置添加就可以了。例如要對按鈕的點擊做出響應,可以這樣寫:
[js] view plaincopy
$("#confetti-btn").click(function (event) {
playTrumpet();
fireConfettiCannon();
});
在JS開始盛行前,這樣的代碼是令人奇怪的,因為很多語言當時都沒有類似的寫法。除了1958年List語言的lambda(匿名)函數有函數表達式功能,C++、Python、C#等語言長時間里都是沒有的。到了現在,lambda已經隨處可見了,這多虧了JS的功勞。例如,
[js] view plaincopy
// 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引入了新的箭頭函數編寫方式。
[js] view plaincopy
// ES5
var selected = allJobs.filter(function (job) {
return job.isSelected();
});
// ES6
var selected = allJobs.filter(job => job.isSelected());
當需要編寫一個簡單的單一參數函數時,可以采用箭頭函數來書寫,標識名=>表達式。這樣就可以省卻function和return的輸入,還有括號,分號等。
當需要編寫一個含有多個參數的函數時,只要把相關參數用括號包起來就好了。
[js] view plaincopy
// 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來編寫的,因此使用了大量的箭頭函數。
除了函數樣式編寫,箭頭函數還可以包含區塊語句而不僅僅是單一表達式。例如:
[js] view plaincopy
/ ES5
$("#confetti-btn").click(function (event) {
playTrumpet();
fireConfettiCannon();
});
ES6的寫法為:
[js] view plaincopy
// ES6
$("#confetti-btn").click(event => {
playTrumpet();
fireConfettiCannon();
});
this是什么?
普通函數與箭頭函數有個微小的不同點。箭頭函數沒有自己的this值,其this值是通過繼承其它傳入對象而獲得的。
JS是如何處理this的呢?這可不是個簡單的問題。其中不論函數有沒有真的需要處理this,函數都是會接收到的。你曾經寫過如下代碼嗎?
[js] view plaincopy
{
...
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值。
在其它場合都使用箭頭函數。
[js] view plaincopy
// ES6
{
...
addAll: function addAll(pieces) {
_.each(pieces, piece => this.add(piece));
},
...
}
什么時候使用箭頭函數
ES6箭頭函數在Firefox、Babel、Traceur、TypeScript等項目都有使用。在1936年,Alonzo Church和Alan Turing一起開發了強大的數學計算機模型,人們習慣把它稱為圖靈機。Church編寫了名為λ-calculus的模型,當時他發現需要在系統使用到“函數”。
這是一個結合Church想法的“程序”示例:
[js] view plaincopy
fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))
JS中可表示為:
[js] view plaincopy
var fix = f => (x => f(v => x(x)(v)))
(x => f(v => x(x)(v)));
這個故事告訴我們,箭頭函數可以幫助打破陳規,從新的角度來思考問題。借助箭頭函數,ES6將會變得更好更強大。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。