首頁  >  文章  >  web前端  >  深入理解JavaScript中的箭頭函數_基礎知識

深入理解JavaScript中的箭頭函數_基礎知識

WBOY
WBOY原創
2016-05-16 15:48:311459瀏覽

從一開始箭頭就是JavaScript 的一部分,在第一個JavaScript 中就建議將內聯的腳本程式碼包裹在HTML 的註解中,這可以防止那些不支援JavaScript 的瀏覽器錯誤滴將你的程式碼顯示為明文。你也許寫過下面這樣的程式碼:

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

古老的瀏覽器將看到兩個不被支援的標籤和一段註釋,只有支援 JavaScript 的新瀏覽器才會將其解析為 JavaScript 程式碼。

為了支援這個古怪的特性,瀏覽器的JavaScript 引擎把 也表示一個單行註釋,與 HTML 不同的是,在 HTML 中,--> 之前的部分是註釋內容,而在 JavaScript 中,在 --> 之後的行才是註釋。

只有當 --> 出現在一行的開始時,才表示該箭頭是一個註釋,因為在其他情況下,--> 是一個操作符(goes to)。

function countdown(n) {
 while (n-->0) // "n goes to zero"
  alert(n);
 blastoff();
}
 
function countdown(n) {
 while (n-->0) // "n goes to zero"
  alert(n);
 blastoff();
}

上面程式碼是真實能運行的。循環運行直到 n 為 0,這並不是 ES6 的新特性,但結合我們熟悉的特性,這具有強烈的誤導性。你能搞清楚上面程式碼的運作情況嗎?你可以在 Stack Overflow 上找到對應的解答。

當然還有一個箭頭,那就是小於等於操作符

  •     goes to 運算子
  •    
  •     => ???

那麼,=> 表示什麼呢?這就是本文將要討論的議題。

首先,我們來談談函數。
無所不在的函數表達式

JavaScript 一個有趣的特點是,任何時候你需要一個函數,你可以很方便地建立它們。

例如,為一個按鈕綁定點擊事件:

$("#confetti-btn").click(
 
$("#confetti-btn").click(

jQuery 的 .click() 方法需要一個函數作為參數,我們可以很方便地就地建立一個函數:

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

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

現在對我們來說,寫這樣的程式碼是最自然的事了。但是在 JavaScript 流行起來之前,這種風格的程式碼看起來還是有些奇怪,因為在其他語言中都沒有這樣的特性。在 1958 年,Lisp 就有了函數表達式,也叫 lambda 函數,而在存在多年的 C 、Python、C# 和 Java 中則沒有該特性。

現在,這四門語言都有了 lambda 表達式,而且新出現的語言都普遍內建了 lambda 表達式。如今 JavaScript 也支援該特性了,這必須感謝那些重度依賴 lambda 表達式的函式庫的開發者,這推動了該特性被廣泛採納。

與其他幾門語言相比,JavaScript 的語法略顯冗長:

// 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
 
// 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());

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

當你需要只有一個參數的函數,箭頭函數的語法可以簡化為 Identifier => Expression,直接省略了 function 和 return 關鍵字,連括號和結尾的分號也同時省略了。

寫一個有多個(或沒有參數,或 Rest 參數和參數預設值,或解構參數)參數的函數,你需要用括號將參數括起來:

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

// ES6
var total = values.reduce((a, b) => a + b, 0);
 
// 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();
});
 
// ES5
$("#confetti-btn").click(function (event) {
 playTrumpet();
 fireConfettiCannon();
});

以下是採用箭頭函數的寫法:

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

要注意的是,使用語句區塊的箭頭函數不會自動傳回一個值,必須明確地使用 return 來傳回一個值。

還有一個忠告,當使用箭頭函數來傳回一個物件時,總是使用括號將傳回的物件括起來:

// create a new empty object for each puppy to play with
var chewToys = puppies.map(puppy => {});  // BUG!
var chewToys = puppies.map(puppy => ({})); // ok

 
// create a new empty object for each puppy to play with
var chewToys = puppies.map(puppy => {});  // BUG!
var chewToys = puppies.map(puppy => ({})); // ok

因為空物件{} 與空語句塊{} 看上去一模一樣,ES6 將永遠把緊跟在=> 後面的{ 當作語句塊的開始,而不是一個對象的開始,那麼puppy => {}就被解析為一個沒有函數體的箭頭函數,而且傳回值為undefined。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn